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

在微服务架构中,一个用户请求往往需要经过多个服务协同处理才能完成。传统的单体日志或单机指标无法回答“这个请求到底慢在哪一个环节”这一关键问题。分布式追踪(Distributed Tracing)正是为解决这一痛点而生,它通过一套标准化的数据模型和传播机制,完整记录请求在分布式系统中的全生命周期。

2.1 核心数据模型:Trace 与 Span

分布式追踪的数据模型由 Trace(追踪)和 Span(跨度)两个核心概念构成,它们之间是树状包含关系。

概念 定义 类比(函数调用栈)
Trace 代表一个完整的请求或事务在分布式系统中的全路径。一个 Trace 由多个 Span 组成,共享同一个 TraceID。 一次完整的 HTTP 请求从入口到返回的全部调用链。
Span 代表 Trace 中的一个命名、定时的操作单元。每个 Span 记录操作名称、开始时间、结束时间、状态以及可选的标签和日志。 函数调用栈中的某一个函数调用。
SpanContext Span 的标识和元数据集合,包含 TraceID、SpanID、Baggage 等,用于跨进程传递追踪上下文。 函数调用时传递的上下文参数。
关键标识符:TraceID 全局唯一标识一次追踪;SpanID 标识 Trace 内的单个 Span;ParentSpanID 标识当前 Span 的父 Span,通过这三个 ID 即可重建完整的调用拓扑树。

2.2 Span 的生命周期与状态

一个 Span 从创建到结束,通常经历以下阶段,每个阶段都对应着可观测性的关键数据采集点:

  1. Span Start:记录操作开始时间戳,生成 SpanID,关联 ParentSpanID。
  2. Span Tag / Log:在 Span 生命周期内,可以动态添加键值对标签(Tags)和结构化日志(Logs),用于记录业务属性或异常事件。
  3. Span End:记录操作结束时间戳,计算耗时,标记最终状态(OK / ERROR)。
  4. Span Export:Span 结束后被采集器(如 Jaeger Agent)上报到后端存储。
常见误区:Span 的结束时间必须在代码中显式调用 span.finish() 或通过 defer 自动结束。忘记结束 Span 会导致该 Span 在 Jaeger UI 中显示为“正在运行”或丢失,造成 Trace 不完整。

2.3 Context Propagation:跨进程的追踪接力

Context Propagation(上下文传播)是分布式追踪能够跨服务串联的“胶水”。它确保当请求从一个服务传递到下一个服务时,TraceID 和 SpanID 能够被正确携带,从而在接收端创建出父子关系的子 Span。

传播方式通常分为两种:

  • 进程内传播:通过线程局部变量(ThreadLocal)或协程上下文传递 SpanContext,保证同一进程内的异步调用能正确关联。
  • 进程间传播:通过序列化 SpanContext 到网络协议的头部(如 HTTP Headers、消息队列的 Metadata)进行传递。Jaeger 遵循 W3C TraceContext 标准,使用 traceparent 和 tracestate 头部。
传播示例(HTTP Header):
# W3C TraceContext 标准格式
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
# 字段说明:版本-TraceID-SpanID-追踪标志(01 表示采样)

2.4 核心概念关系图

下图展示了 Trace、Span 以及 Context Propagation 在微服务调用中的协作关系:

Trace、Span 与 Context Propagation 关系图 Trace、Span 与 Context Propagation 关系图 Trace(完整请求链路) Service A Span: /api/order SpanID: A1 Service B Span: /inventory SpanID: B1 Service C Span: /payment SpanID: C1 HTTP traceparent gRPC traceparent Context Propagation 传播过程 TraceID: 0af7651916cd43dd8448eb211c80319c(所有 Span 共享) Span 树状结构(Parent-Child 关系) Root Span (A1) Child Span (B1) Child Span (C1)

2.5 采样策略:控制数据量与成本

在高并发生产环境中,为每一个请求都生成完整的 Trace 会产生巨大的存储和网络开销。因此,分布式追踪系统必须依赖采样(Sampling)策略来有选择地收集数据。常见的采样策略包括:

采样策略 工作原理 适用场景
头部采样(Head-Based) 在 Trace 入口处(如网关)根据概率或速率决定是否采样,后续所有 Span 继承该决策。 低延迟、高吞吐场景,采样率固定(如 1%)。
尾部采样(Tail-Based) 先收集所有 Span,在 Trace 结束后根据规则(如错误、慢请求)决定是否保留。 需要保证错误 Trace 100% 采集的场景。
自适应采样 根据系统负载动态调整采样率,在低负载时提高采样率,高负载时降低。 流量波动较大的生产环境。
Jaeger 默认策略:Jaeger Agent 支持通过配置文件或远程采样策略(Remote Sampling)动态下发采样率。推荐在生产环境使用“基于速率”的采样,例如每秒最多采集 10 个 Trace,避免突发流量导致存储打满。

2.6 本章小结