2. Trace 基础概念:Span、Trace、Context Propagation、分布式追踪核心术语

分布式追踪(Distributed Tracing)是构建可观测性体系的三大支柱之一。在微服务架构中,一个用户请求往往需要跨越多个服务、多个进程、多个网络节点才能完成。Trace 技术通过一套标准化的数据模型和传播机制,将一次请求的完整调用链还原出来,让工程师能够精确地定位性能瓶颈和错误根因。

本章将围绕 Trace 领域的四个核心概念展开:Span(跨度)、Trace(追踪)、Context Propagation(上下文传播),以及相关的分布式追踪术语。理解这些基础概念是后续实现 Trace 监控与 ErrorHandler 报警联动的前提。

2.1 Span:追踪的最小工作单元

Span 是分布式追踪中最基本的数据单元,它代表一次请求中某个特定操作的时间片段。例如,一个 HTTP 请求的接收、一次数据库查询、一次消息队列的发送,都可以被建模为一个 Span。

每个 Span 包含以下关键属性:

属性 说明 示例值
Span ID 全局唯一的标识符,用于唯一标识一个 Span abc123def456
Trace ID 所属 Trace 的全局唯一标识符,同一 Trace 内所有 Span 共享此 ID trace-001-xyz
Parent Span ID 父 Span 的 ID,用于构建调用链的父子关系;根 Span 此字段为空 parent-span-789
Operation Name 描述 Span 代表的操作名称,通常为 服务名.接口名 order-service.createOrder
Start Time / End Time Span 的开始和结束时间戳,用于计算耗时 1710000000.123 / 1710000000.456
Status 操作结果状态:OK、ERROR、UNSET ERROR
Tags / Attributes 键值对形式的元数据,用于附加业务或技术上下文 http.status_code=500, error.message=timeout
Events / Logs Span 生命周期内发生的结构化日志事件 exception.stacktrace
实践要点:Span 的粒度需要根据业务场景权衡。过粗的 Span 会丢失细节,过细的 Span 会增加存储和传输开销。通常建议将每个外部调用(HTTP、RPC、DB、MQ)作为一个独立的 Span。

下面是一个 Span 生命周期的内联 SVG 示意图,展示一个 Span 从创建到结束的完整过程:

Span 生命周期与核心属性 Span: order-service.createOrder Start T1 End T2 Span ID abc123def456 Parent: parent-span-789 Tags http.status_code=500 error.message=timeout Status ERROR Duration: 333ms

2.2 Trace:一次请求的完整调用链

Trace 是由一组具有相同 Trace ID 的 Span 构成的树形结构,它完整地记录了一次请求从入口到出口经过的所有服务、组件和操作。Trace 的根 Span(Root Span)代表请求的入口点,其子 Span 代表后续的各个调用步骤。

Trace 的核心特征:

  • 全局唯一 Trace ID:所有 Span 共享同一个 Trace ID,用于关联和检索。
  • 树形层级结构:通过 Parent Span ID 形成父子关系,根 Span 无父节点。
  • 端到端时间线:Trace 的起始时间为根 Span 的开始时间,结束时间为最后一个 Span 的结束时间。
  • 跨服务边界:Span 可以分布在不同的进程、主机甚至不同的数据中心。
关键理解:Trace 不是日志的简单聚合,而是通过上下文传播机制将分散在各处的 Span 按照因果关系重新组装成完整的调用拓扑。这种因果关系是定位分布式系统故障的核心线索。

下面是一个典型的 Trace 结构 SVG 图,展示一个用户请求经过 API 网关、订单服务、支付服务和数据库的完整调用链:

Trace 树形结构示例:用户下单请求 Trace ID: trace-order-20250301-001 Root Span: api-gateway.handleRequest Child Span: order-service.createOrder Child Span: payment-service.processPayment Leaf Span: order-db.updateOrderStatus T0 T1 T2 T3 Trace 结构说明 每个 Span 通过 Parent Span ID 指向父节点,形成从根到叶的完整调用路径。Trace 的总耗时 = T3 - T0。

2.3 Context Propagation:跨服务的上下文传递

Context Propagation(上下文传播)是分布式追踪的核心机制,它负责将 Trace 上下文(包括 Trace ID、Span ID 等信息)从一个服务传递到下一个服务,确保所有 Span 能够归属于同一个 Trace。

上下文传播的两种主要方式:

传播方式 适用协议 传播载体 示例
W3C Trace Context HTTP / HTTPS HTTP Headers traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
gRPC Metadata gRPC Metadata 键值对 grpc-trace-bin 或 W3C 标准
Message Queue Kafka / RabbitMQ 消息头 / 属性 Kafka Headers 中注入 Trace ID
进程内传播 线程 / 协程 线程局部变量 / 上下文对象 Python contextvars 或 Java ThreadLocal
常见陷阱:上下文传播丢失是分布式追踪中最常见的问题。例如,异步消息处理中未正确传递 Trace 上下文,会导致后续 Span 成为孤儿 Span(Orphan Span),无法与父 Trace 关联。务必在异步边界(线程池、消息队列、定时任务)显式传递上下文。

下面是一个 Context Propagation 的跨服务传递流程 SVG 图:

Context Propagation 跨服务传递流程 服务 A API 网关 Span ID: A-001 服务 B 订单服务 Span ID: B-002 服务 C 支付服务 Span ID: C-003 HTTP Header traceparent gRPC Metadata grpc-trace-bin 传播的上下文内容 Trace ID: trace-order-20250301-001 | Parent Span ID: A-001 | 其他 Baggage 信息 每个服务在接收到请求后,从上下文中提取 Trace ID 和 Parent Span ID,创建新的子 Span 并继续向下游传播。

2.4 分布式追踪核心术语速查

除了 Span、Trace 和 Context Propagation 之外,分布式追踪领域还有一组常用的核心术语,理解它们有助于后续章节的学习:

术语 英文 定义 与 ErrorHandler 的关联
根 Span Root Span Trace 中的第一个 Span,无父 Span,代表请求的入口 根 Span 的错误通常代表整个请求失败
子 Span Child Span 由父 Span 创建的 Span,代表一次子调用 子 Span 的错误可能是局部异常,需结合父 Span 判断影响范围
Span 上下文 Span Context 包含 Trace ID、Span ID 和 Baggage 的不可变对象 ErrorHandler 可通过 Span Context 获取完整的调用链信息
Baggage Baggage 随上下文传播的键值对,用于传递业务级信息 可用于传递用户 ID、请求来源等,辅助报警上下文
采样 Sampling 按策略选择部分 Trace 进行记录,控制数据量 错误 Span 通常使用强制采样,确保不丢失异常数据
Trace 导出器 Exporter 将 Span 数据发送到后端存储(如 Jaeger、Zipkin)的组件 ErrorHandler 报警触发时可主动导出当前 Trace 快照
服务图 Service Graph 基于 Trace 数据生成的微服务调用拓扑图 帮助快速定位错误传播路径
学习建议:在后续的课程中,我们将基于 OpenTelemetry 标准实现 Trace 的采集和传播。建议你现在就安装一个 Jaeger 或 Zipkin 的本地环境,手动发送几个 Span 观察 Trace 的树形结构,这比单纯阅读概念要直观得多。

2.5 本章小结

本章介绍了分布式追踪的四个基础概念:

  • Span:最小工作单元,包含操作名称、时间戳、状态和标签等属性。
  • Trace:由共享同一 Trace ID 的 Span 构成的树形调用链。
  • Context Propagation:跨服务传递 Trace 上下文的机制,是分布式追踪的基石。
  • 核心术语:根 Span、子 Span、Span 上下文、Baggage、采样等。