有代理 Span,不代表有一条完整的 trace

Envoy 可以为经过它的请求产生 Span,但一次 frontend → orders 调用链(orders 先调用 inventory,成功后再调用 external-stub) 会跨多个应用和代理。上游代理发出的 Span 想与下游代理的 Span 连成同一条 trace,应用必须把收到的追踪上下文带到新发起的请求;代理无法替应用跨越一个由应用新建的 HTTP 请求边界。X-Request-ID 方便人工关联日志,但不是 W3C traceparent 的替代品,两个值都出现也不保证父子关系正确。

这恰好是累计工程中一个尚待实现的实验对照:目前 examples/service-mesh/apps/mesh-demo/main.go 的下游 fetch 只设置 X-Request-ID,没有传播 traceparent/tracestate 或 B3,也没有应用 Span。不能拿这个工程当前的请求日志称为“代理链路追踪已成功”。下一步最小改动是为该调用链增加可开关的上下文抽取与注入,选定一套传播格式,增加必要的应用 Span;不要同时混用未约定的格式,也不要让客户端自由输入的 header 充当可信身份。

应用跨请求转发 traceparent 时代理 Span 才可关联;停止传播仍可能保持业务成功

传播、采样和收集是三个独立关口

先固定输入请求的 trace ID,令 frontend、orders 在同一格式下传播,再观察下游代理和应用 Span 的 trace ID、parent ID。关闭 frontend → orders 这一跳的传播作负例:业务请求依然可能返回 200,但下游 Span 应失去预期的父子关系;恢复传播后重新核对,不以“页面显示几个 Span”代替 parent ID 检查。

即使传递了 traceparent,采样策略仍可能不记录所有请求。可在资源允许的隔离实验中暂设确定的高采样率,记录配置、请求数与实际生成的 Span 数;不能将测试用 100% 采样写成生产建议。代理把 Span 发给 Collector 与 Collector 实际接收、导出至查询后端又是两个关口。单独断开测试用 Collector 或错误配置导出目标时,业务仍可能成功,此时必须比对代理导出错误、Collector 接收/导出计数和后端查询结果,不能说“没有 trace 就没有请求”。

观察关口 成功与失败对照 实际结果
上下文传播 开启/关闭应用转发,核对 trace ID 与父子关系 NOT_RUN:无 Envoy/Istio,应用传播未实现
采样 固定采样配置与输入集合,比较代理生成集合 NOT_RUN
导出 Collector 正常/不可用,比较接收与后端可查询集合 NOT_RUN:无 Collector/追踪后端

每个输入保留独立请求 ID,记录应用结果、代理 Span、Collector 和查询后端四层证据;不使用单次有迹象的请求推论整个链路不会断。应用成功、代理生成、Collector 收到、后端可查是四个不同命题。

练习与参考解答

  1. 网关和库存代理各显示一个 Span,是否已经证实它们属于同一调用?参考解答:尚未。需要核对 trace ID、parent ID,以及跨应用传播头与实际调用路径。
  2. 客户端返回 200,但后端查不到 trace,优先改业务代码吗?参考解答:先看传播、采样、代理导出、Collector 接收及后端写入是否各自成立;缺失不一定发生在业务层。

官方资料与系列导航

系列导航:23 网格指标怎样用于 SLO → 24 自动追踪为什么仍会断链(本文)→ 25 503、连接重置与尾延迟如何定位。