链路追踪连接一次请求中已被记录的操作
分布式链路追踪利用共同的链路标识和明确的关系,连接一次请求中被记录下来的操作。一个跨度表示一项操作,带有开始与结束时间、属性、事件和状态。当结账请求依次涉及应用、库存服务和支付服务时,这些信息可以帮助我们还原处理路径。但最终图形取决于哪些位置做了插桩、哪些数据通过采样并成功导出,不能把它当成请求实际执行过的全部动作清单。 链路标识用于归集相关跨度,跨度标识用于区分同一条链路中的具体操作,父跨度标识则连接直接的上游操作。通过 HTTP 跨越边界时,W3C 的 traceparent 请求头携带链路标识、发送端跨度标识和链路标志。接收端必须提取这些上下文,再创建自己的跨度。仅仅在几条互不关联的日志里写入同一个请求编号,并不会自动形成可供追踪系统识别的跨度父子关系。对于由多个上游共同触发的工作,可以用跨度链接表达额外关系,而不是给一个跨度分配多个父级。 链路 A 与 B 是原文两组链路的图解名称,不是真实标识。图解仅依据原文叙述与未执行代码;历史状态仍为已阅读、执行受阻,本次没有重跑或新增运行验证。箭头长度不表示耗时。 先读关系,再分析耗时 一个服务端跨度可能包含数据库操作,也可能包含多个同时进行的外部请求。把所有跨度的时长相加,会重复计算重叠的时间;如果兄弟跨度并发执行,用父跨度时长减去所有子跨度时长,也可能得到毫无意义的负数。应当阅读时间线,判断哪些区间位于影响请求完成的关键路径。跨机器的时钟差异以及缺失的插桩,还会限制我们对图上空白区间的解释精度。 跨度状态也需要单独理解。HTTP 响应码、异常事件和 OpenTelemetry 的错误状态是三份不同的信息,插桩库可能依据自己的约定将它们关联起来。手工记录异常时,不能因此假定所有有关的状态字段都已经改变。服务名称等资源属性回答数据由哪个服务发出,而某个跨度的名称、属性和事件回答该服务中发生了什么操作。混淆这两个层次,会使跨服务排查失去可靠的定位依据。 坏掉的样子 代理可能丢弃传播请求头,接收服务也可能没有调用上下文提取逻辑。此时业务请求已经成功抵达下游,但下游工作在追踪系统里属于另一条链路。还有一种错误是链路标识相同,父跨度却连接错误:数据看似聚到一起,实际因果位置已经不对。验证一个服务边界时,既要检查链路标识,也要检查直接父跨度,不能只确认后端收到了几条跨度就宣布传播正确。 找不到某个跨度,可能是采样舍弃、尚未插桩、异步执行中丢失上下文,或者导出失败造成的,不能据此证明该操作没有运行。同样,界面里一片绿色,也不代表所有下游依赖都成功了。需要结合请求最终结果指标和相关日志,核对采集器及导出器的健康状况,然后再解释链路图。不完整的数据可以帮助提出问题,却不能独自证明一条没有观测缺口的完整处理路径。 快速验证 先创建 Python 虚拟环境,安装 opentelemetry-sdk==1.35.0,其依赖会安装匹配的 API 版本。将以下代码保存为 trace-flow.py,再使用该环境的 Python 执行;原文报告曾使用 Python 3.14.4 执行该练习。本次修订保留原练习但未重新运行,当前执行检查仍受阻。脚本启动仅监听本机回环地址的 HTTP 服务,分别为调用者和接收者创建追踪提供器,把完成的跨度写入内存导出器。请求结束后会关闭服务,无须准备独立的遥测采集器。获得授权后运行之前,还应确认代理配置绕过 127.0.0.1,否则 urllib 可能使用已配置的代理。建立本地监听和发起 HTTP 请求需要合适的可丢弃环境。 ...