Skip to content

采样与对比:策略、Zipkin 并入与 Tempo 取舍

基于 Jaeger 1.x + OpenTelemetry · 核于 2026-08

速查

  • 为什么采样:高流量场景不可能全采 trace(每请求一个,存储+处理成本爆炸),必须采样控制上报量。但采样有损——可能丢掉关键错误 trace。
  • 头部采样(Head-based):在请求入口决定是否采样,被采的整条 trace 都采,被丢的整条都丢。简单、低延迟,但入口采样 1% 意味着 99% 请求连错误 trace 都没有(稀有错误可能漏)。
  • 尾部采样(Tail-based):在请求结束后按条件决定是否采(如 is error? latency > 1s? has specific tag?)。精准(保证采到错误与慢请求),但要在 Collector 缓存所有 trace 到结束(内存+延迟)。
  • 采样策略:①概率(probabilistic)——按固定概率(如 1%);②速率限制(ratelimiting)——每秒最多 N 个;③远程(remote)——中心化动态配置,可按服务/端点不同;④常量(const)——全采或全不采(测试用)。
  • Zipkin 并入 OTel:Zipkin(Twitter 2012)是早期开源追踪,现基本并入 OTel 生态——用 OTel SDK 埋点,Zipkin 作可选后端。Jaeger 支持接收 Zipkin 格式数据(迁移友好)。新项目用 OTel SDK + Jaeger/Tempo,不建议再上 Zipkin。
  • Jaeger vs Tempo:Jaeger 原生支持属性检索(按 service/operation/tags/latency 查 trace,强但存储贵);Tempo 设计相反——按 traceID 查找(不索引属性,省存储约 Jaeger 1/N),早期不支持属性检索(只能 traceID),新版 TraceQL 补齐属性检索。
  • 选型:要强属性检索(不知道 traceID 时按 service/错误查)选 Jaeger;要省存储+已上 Grafana 栈选 Tempo。

一、为什么必须采样

分布式追踪的根本矛盾:每请求一个 trace,数据量 = 请求量。高流量系统(如电商秒杀、API 网关)每秒几万请求,全采 trace 的成本(存储+网络+处理)爆炸。所以必须采样——只保留一部分 trace。但采样有损:

  • 错误可能漏采:如果采样率 1%,恰好那个 500 错误的请求被丢,就完全没有它的 trace,排障无据。
  • 慢请求可能漏采:同理,慢请求稀有,1% 采样可能恰好错过。
  • 尾部采样的价值:等请求结束再决定,保证采到错误/慢请求。

二、头部采样 vs 尾部采样

头部采样(Head-based,入口决定)

请求到 gateway → gateway 决定是否采样(按概率 1% 或速率)
  → 采样的请求:traceID 标记 sampled=1,整条 trace 所有 span 都采
  → 不采样的请求:所有 span 都不采(最终不导出到后端)
  • 优点:简单、低延迟(入口决定,无需缓存)、SDK 端实现。
  • 缺点:入口采样 1% 意味着 99% 请求(包括错误/慢请求)无 trace——稀有错误可能漏。

尾部采样(Tail-based,结束决定)

所有请求的 span 都先发到 OTel Collector,Collector 缓存
  → 请求结束(trace 完整)
  → Collector 按条件判断:
     - is error?(error=true)→ 采
     - latency > 1s?(慢请求)→ 采
     - has tag X?(特定属性)→ 采
     - 其他 → 按低概率采(如 0.1%)
  → 被采的导出到后端,其他丢弃
  • 优点:精准——保证采到所有错误、所有慢请求,稀有错误不漏。
  • 缺点:①要在 Collector 缓存所有 trace 到请求结束(内存开销);②延迟(必须等结束);③Collector 复杂度增加。
  • 实现:OTel Collector 的 tail_sampling processor,配置策略组合。

选型

  • 头部采样:流量均匀、错误率稳定、预算敏感——简单够用。
  • 尾部采样:错误稀有但关键、慢请求难复现、要保证采到关键 trace——值得复杂度。

三、采样策略详解

策略配置适用
constsamplingProbability: 0 或 1(全不采/全采)测试/调试
probabilisticsamplingProbability: 0.01(1%)流量均匀,预算敏感
ratelimitingmaxTracesPerSecond: 10平滑流量,突发流量保护
remote中心化配置,动态调整生产推荐,可按服务/端点不同
tail sampling(在 Collector)按条件(error/latency/tag)精准,保证采到关键 trace

远程采样(生产推荐)

yaml
# Jaeger 远程采样配置
sampling:
  strategies:
    - service: api-gateway
      type: probabilistic
      param: 0.5            # 网关 50%
    - service: payment-svc
      type: ratelimiting
      param: 100            # 支付服务 100 traces/s(关键服务多采)
  • 动态调整:不用重启服务,改中心配置即生效。
  • 按服务/端点:关键服务(支付)高采样,普通服务低采样。

四、Zipkin:并入 OTel 生态

Zipkin 是 Twitter 2012 开源的早期分布式追踪系统:

  • 历史地位:最早的成熟开源追踪系统,普及了 trace/span 模型。
  • 现状:基本被 OTel + Jaeger/Tempo 取代——OTel SDK 厂商中立,Zipkin 作为可选后端存在。
  • Jaeger 兼容 Zipkin:Jaeger Collector 可接收 Zipkin 格式数据(/api/v1/spans 端点),从 Zipkin 迁移到 Jaeger 无需改业务代码。
  • 新项目建议:直接用 OTel SDK + Jaeger/Tempo,不上 Zipkin(Zipkin 维护活跃度低于 OTel 生态)。

五、Jaeger vs Tempo:检索与存储的取舍

Jaeger 和 Tempo(Grafana 系)都是 OTel trace 后端,但设计哲学相反:

维度JaegerTempo
索引模型索引属性(service/operation/tags)只索引 traceID(不索引属性)
属性检索(按 service/错误/latency 查)弱(早期只能 traceID,新版 TraceQL 补齐)
按 traceID 查支持核心设计(高效)
存储成本高(索引属性)低(不索引属性,约省 N 倍)
生态CNCF / UberGrafana LGTM
可视化自带 UIGrafana

Jaeger 的属性检索价值

场景:用户报「下单偶发失败」,但你不知道 traceID
Jaeger 查询:service=order-svc AND operation=POST /api/order AND tags.error=true
→ 返回所有出错的下单 trace,定位根因
  • 不知道 traceID 时:按属性查(service/operation/tags)找到问题 trace。
  • 代价:要索引所有属性,存储与索引成本高。

Tempo 的 traceID 查找价值

场景:从指标/Sentry 拿到 traceID(Exemplar/error event 带 traceID)
Tempo 查询:GET /api/traces/<traceID>
→ 直接返回该 trace(高效,因不索引属性省存储)
  • 配合 LGTM 联动:从 Grafana 指标 Exemplar → Tempo trace → Loki 日志,traceID 贯穿。
  • 代价:不知道 traceID 时难找问题(早期),新版 TraceQL 补齐属性检索但仍弱于 Jaeger。

选型决策

  • 选 Jaeger:①需要强属性检索(按 service/operation/tags 查);②不知道 traceID 时要找问题 trace;③CNCF 生态、Uber 出品信任度高;④预算能承担存储成本。
  • 选 Tempo:①已上 Grafana 栈,要 traceID 四支柱联动;②存储成本敏感(Tempo 省 N 倍);③查询模式是「先拿到 traceID 再查」(配合指标 Exemplar)。
  • 两者都支持 OTel:埋点一次,后端可切换/并存。

六、典型集成:OTel + Jaeger 全链路

应用(OTel SDK 埋点)
  → OTLP 导出
  → OTel Collector(可选,做 batch + tail sampling)
  → Jaeger Collector
  → Storage(Cassandra/ES)
  → Jaeger UI(瀑布图查 trace)

配合:
  - Prometheus 指标(P99 突增)
  - Sentry 错误(带 traceID)
  - ELK/Loki 日志(按 traceID 关联)
  → 一个请求从指标→追踪→日志→错误全链路可追溯

下一步

掌握了采样策略与 Zipkin/Tempo 对比后,可看本叶参考(OTel SDK 集成速查、span 属性、采样配置、易错点),或横向看其他可观测性工具——Prometheus(指标)、Grafana(可视化)、ELK(日志)、Sentry(错误)。