本页目录

分布式追踪

一次请求跨越十几个微服务后,怎么知道时间花在了哪?分布式追踪给每个请求分配一个 trace ID,跨服务的调用关系通过 context propagation 传递 span context(trace ID + parent span ID + 采样标志),把散落在各节点的片段拼成完整调用链。采样策略是成本控制的关键:全量采太贵,固定比例采会漏掉长尾错误,tail-based 采样在完成后再决定保留哪些 trace。

Dapper (Google 2010) → OpenTelemetry

Google 的 Dapper 论文启发了开源生态:Zipkin (Twitter) → Jaeger (Uber) → OpenTracing + OpenCensus → OpenTelemetry (CNCF, 当前标准)。

Trace 与 Span

Trace 与 Span 结构:一个 Trace 由多个 Span 组成 Trace — 一次端到端请求的所有 spans 的集合 Span — 一次 RPC 调用的记录,含以下 7 个字段 trace_id trace 的唯一 ID span_id 本 span 的唯一 ID parent_id caller span 的 ID(root span 无 parent) operation "GET /api/users" / "SELECT * FROM users" start/end 时间戳 status OK / ERROR(含错误详情) attributes 自定义 tags(http.status_code, db.statement, ...) 关键结构:parent_id 把散落在各服务节点的 span 拼回一棵树—— root span 无 parent,子 span 都记录 caller 的 span_id。 Span 调用层级树:一次 /api/order 请求的父子结构 Trace: user request → /api/order Span A · GET /api/order root span(无 parent) Span B · auth-service.ValidateToken 校验用户 token Span C · order-service.CreateOrder 创建订单 Span D · postgres: INSERT INTO orders 实际落库操作(叶子 span) parent_id 把 auth-service / order-service / postgres 的 span 拼回一棵树: root span(A)无 parent,子 span 记录 caller 的 span_id,层级由此确定。

Context Propagation

跨服务的 trace 传递是关键——每个服务必须知道"我是哪个 trace 的哪个 span":

HTTP: traceparent: 00-<trace_id>-<span_id>-<trace_flags>
W3C Trace Context (标准): traceparent header
gRPC: metadata (grpc-trace-bin)
Kafka: message headers

trace_flags: bit 0 = SAMPLED (是否被采样), 其他 bits reserved。

内部实现:tracer 在调用下游服务时,创建新的 span (作为 caller span 的 child),将 trace_id + new_span_id 放入 outbound headers。下游的中间件/库(HTTP client, gRPC stub, DB driver)在收到 response 时提取 trace context,自动创建 child span。

Sampling

全量采集 → 开销不可接受(每条 span 需要 ~1μs overhead + 网络/存储成本)。需要采样策略:

  • Head-based (概率): 在 trace 开始时决定是否采样(随机 1/100 或 1/1000)。简单,但可能漏掉包含错误的 trace。
  • Tail-based (智能): 缓存所有 spans(本地 buffer),trace 完成后根据 result (ERROR? latency > SLO?) 决定是否保留。能保 error 不丢,但内存开销大。OpenTelemetry 的 tailsampling processor 实现此策略。

Jaeger 部署 (参考)

# Agent (每 host 一个, 接收 app 通过 UDP 发来的 spans)
# Collector (中心, 从 agents 收 → 写入存储)
# Storage (Cassandra/Elasticsearch)
# Query (UI + API)

参考

  • 论文⁠: "Dapper, a Large-Scale Distributed Systems Tracing Infrastructure" (Google, 2010)
  • OpenTelemetry: opentelemetry.io/docs/specs/otel/trace
  • Jaeger: jaegertracing.io

Keywords: distributed tracing, Dapper, OpenTelemetry, Span, trace context propagation, W3C Trace Context, sampling