土法炼钢 · 系统与基础设施

【可观测性工程】Traces 栈与采样:Jaeger、Tempo、Zipkin、SkyWalking

文章导航

分类入口
architectureobservability
标签入口
#tracing#jaeger#tempo#skywalking#zipkin#opentelemetry#sampling#tracecontext#tail-sampling#propagation

目录

Traces 栈与采样:Jaeger、Tempo、Zipkin、SkyWalking

用户在 Jaeger UI 搜 duration > 5s,等了两分钟——不是 Jaeger 慢,是 Elasticsearch 在数十亿 Span 上做范围扫描。Trace 写入量是 Metrics 的几十到几百倍;采样策略比后端选型更重要

本文深入 Jaeger、Grafana Tempo、Apache SkyWalking 的存储模型与架构取舍,讲解 W3C TraceContext / B3 传播、OpenTelemetry Collector tail_sampling 配置,并用假设模型估算存储量。前置:数据模型OpenTelemetry

头部采样 vs 尾部采样

一、从 Dapper 到 OpenTelemetry

Google Dapper(2010)提出 trace tree + 采样;Zipkin(2012)、Jaeger(2017)、Tempo(2021)、SkyWalking(2015)演进。

    OpenTelemetry(2019)统一 API/SDK/OTLP——竞争从 SDK 转向后端与采样。

二、Span、Trace 与 SpanContext

三、Jaeger 深度拆解

组件:Collector(接收/采样/写存储)、Query(UI/API)、Ingester(Kafka 消费)。Agent 已废弃,由 OTel Collector 替代。

    **存储后端**:
    | 后端 | 模型 | 搜索 |
    |------|------|------|
    | Elasticsearch | 每 span 文档 + 倒排 | 毫秒级 tag 搜索 |
    | Cassandra | trace_id 宽行 | 有限 |
    | Badger | 嵌入式 KV | 开发 |

    生产 ES mapping 必须预定义——动态 mapping + 高基数 tag = 集群事故。

    ```mermaid
    flowchart LR
      SDK[OTel SDK] --> Coll[OTel/Jaeger Collector]
      Coll --> ES[(Elasticsearch)]
      Query[Jaeger Query] --> ES
    ```

四、Grafana Tempo 深度拆解

哲学:只索引 trace_id + 时间 + 少量 resource;Span attribute 不建倒排。

    路径:Distributor → Ingester(WAL)→ Parquet Block → S3 → Querier。

    TraceQL:`{ duration > 500ms && status = error }` 并行扫描 block——秒级。

    与 Grafana:Loki `trace_id` → Tempo;Exemplar → Tempo。

    ```mermaid
    flowchart TB
      D[Distributor] --> I[Ingester + WAL]
      I --> S3[(Object Storage)]
      Q[Querier] --> S3
      QF[Query Frontend] --> Q
    ```

五、Apache SkyWalking 深度拆解

中国社区 APM 代表;Apache 顶级项目。

    **差异**:
    - Java Agent 字节码增强(ByteBuddy),少改代码  
    - Segment 模型 + OAP 分析层  
    - 服务拓扑、端点依赖、JVM/DB 监控开箱即用  
    - 存储:ES、BanyanDB、TiDB 等  

    vs Jaeger/Tempo:SkyWalking 是 **APM 平台**,不是纯 Trace 存储。

    OTel 兼容在增长,但原生 Sw8 协议仍常见于国内存量系统。

六、Zipkin 与生态位

Zipkin 轻量、Thrift/JSON API;适合中小规模或 Kafka 缓冲架构。与 Jaeger 类似全索引 ES 路线,新项目更常 OTel Collector → Tempo/Jaeger v2。

七、采样:为什么必须采

假设:\(Q=10000\) req/s,每请求 10 spans,全量:

    $$N_{day} = 10000 \times 86400 \times 10 = 8.64 \times 10^9 \text{ spans/day}$$

    见 [数据模型 §4.4](../05-data-model/data-model.html) 存储公式——全量不可规模化。

八、头部采样(Head-based)

入口按 trace_id hash 决策;trace_flags sampled bit 传播。

    优点:零缓冲、各节点本地决策。  
    缺点:**不可逆**——错误请求可能落在未采样分区。

    Jaeger:`probabilistic`/`rateLimiting`/`remote` 策略。

九、尾部采样(Tail-based)

Collector 缓冲 trace 完整 span 集,按 status=ERRORduration>阈值 保留。

    优点:高价值 trace 不丢。  
    缺点:内存、延迟、需 `wait` 窗口。

    ![采样策略对比](./sampling-comparison.svg)

十、OpenTelemetry tail_sampling 配置

yaml processors: tail_sampling: decision_wait: 10s num_traces: 100000 expected_new_traces_per_sec: 1000 policies: - name: errors type: status_code status_code: status_codes: [ERROR] - name: slow type: latency latency: threshold_ms: 2000 - name: baseline type: probabilistic probabilistic: sampling_percentage: 1

    **组合策略**:errors OR slow OR 1% baseline——生产常见。

    与 [埋点哲学](../04-instrumentation-philosophy/instrumentation-philosophy.html) 采样决策树对齐。

    `decision_wait` 须大于服务 p99 尾延迟,否则 span 未到齐误判。

十一、传播协议

协议 | Header | 场景 | |——|——–|——| | W3C TraceContext | traceparent, tracestate | 标准首选 | | B3 | X-B3-TraceId, X-B3-SpanId, X-B3-Sampled | Zipkin 遗留 | | Jaeger | uber-trace-id | 老 Jaeger 客户端 |
    OTel:`OTEL_PROPAGATORS=tracecontext,baggage`(按需加 b3)

    **翻车**:
    - HTTP/2 header 小写;网关 strip trace headers  
    - Kafka/RabbitMQ 不自动传播——producer inject、consumer extract  
    - 跨语言 `trace_flags` 未转发 → 下游不记录

十二、Jaeger vs Tempo vs SkyWalking 选型

条件 | 推荐 | |——|——| | LGTM 全家桶 | Tempo | | 强 attribute 搜索 | Jaeger+ES | | 国内 APM 开箱 | SkyWalking | | >10B spans/day | Tempo | | OTel 多后端 | Collector → 任选 |

十三、工程坑点

  1. traceparent 在网关丢失
    2. NTP skew → clock skew 警告
    3. 循环内创建 span → ingester OOM
    4. ES 按天 index 分片过大
    5. tail_sampling num_traces 过小 → 决策队列丢
    6. 头部 100% + 尾部重复保留 → 存储翻倍
    7. service.name 不一致 → 拓扑断裂

十四、落地清单

十五、关键概念回顾

十六、下一步

Traces 之后进入 OpenTelemetry 深入 或内核追踪 17-kernel-tracing

参考资料

  1. B. H. Sigelman et al., Dapper, Google Technical Report, 2010
  2. W3C, Trace Context, https://www.w3.org/TR/trace-context/
  3. Jaeger Architecture, https://www.jaegertracing.io/docs/latest/architecture/
  4. Grafana Tempo Architecture, https://grafana.com/docs/tempo/latest/architecture/
  5. Apache SkyWalking, https://skywalking.apache.org/docs/
  6. OpenTelemetry Tail Sampling Processor, https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor
  7. OpenTelemetry Propagation, https://opentelemetry.io/docs/concepts/context-propagation/

上一篇日志管道:Fluent Bit、Vector、Logstash、Cribl 的取舍

下一篇内核追踪:ftrace、kprobe、uprobe、tracepoint 生产实战

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。


By .