网关到订单服务这一段在 Jaeger 里是断开的两条 trace,网关 traceId 是 4f2a9c,订单服务是 b71e30。网关访问日志里有 X-B3-TraceId,下游收到的请求头里没有这一项。日志里能对上时间点,这种反而好排。

网关的路由过滤器里用了 removeRequestHeader 清掉一批内部头,X-B3 系列在里面被一并删掉。下游 SDK 拿不到上下文就新建 trace,父子关系断在这里。跨线程的 RestTemplate 也没注册拦截器,即使头传过来也带不进子调用。这一点先确认清楚,后面就不用反复试。

curl -H 'X-B3-TraceId: 4f2a9c' -H 'X-B3-SpanId: 11' http://gw/api/order/1 -v
kubectl logs deploy/gateway | grep -i 'x-b3'

「B3 头未透传」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。

报错里带路径的,先去看那个路径在不在、权限对不对。

处理上按这个顺序:在网关打印转发前后的全部请求头 对比差异;把 X-B3-TraceId SpanId ParentSpanId Sampled 加进白名单;下游注册 ClientHttpRequestInterceptor 把当前上下文写进请求头;用一次下单请求核对两侧 traceId 是否一致。

结果对不对很好判断,Jaeger 里网关和订单服务落在同一条 trace 下,父子 span 关系完整。

作者 9823189