OpenTelemetry 采样详解:头部采样与尾部采样怎么选
全量采集链路在高并发下成本高企,采样是控制可观测性支出的核心手段。本文系统对比头部采样(Head-based)与尾部采样(Tail-based)的原理、优劣与 OpenTelemetry 实现方式,并给出结合观测云控制链路成本的落地建议。
采样(Sampling)是在保证问题可定位的前提下,只保留一部分链路数据的策略——它的本质是一道经济题:链路数据的价值密度极不均匀(99% 的健康请求告诉你"一切正常",1% 的错误链路才是排障金矿),而全量存储的成本随流量线性上涨。
核心要点速览
- 采样的动机:控制存储与传输成本,同时保住排障所需的关键链路;
- 头部采样在请求入口处决策,简单高效但"盲选"——可能丢掉后来出错的链路;
- 尾部采样等链路完成后按结果(错误、延迟、路径)决策,精准但需要缓存与汇聚;
- OTel 的尾部采样依赖 Collector 的
tail_sampling处理器,且要求同一条链路的所有 Span 汇聚到同一实例。
为什么必须认真对待采样?
一个中等规模的微服务系统,每秒产生数万 Span 稀松平常。按每条 Span 1-2KB 估算,一天就是几 GB 到几十 GB 的链路数据。更要命的是,这些数据里绝大多数是重复的健康请求——存它们几乎不产生洞察,却实打实地消耗存储与带宽。
但采样不是"砍数据"这么简单,采错了就是事故:排障时发现报错链路偏偏没采到,可观测性体系瞬间失去信任。因此采样策略的核心问题是——在什么时候、依据什么信息做丢弃决策。
头部采样:请求起点处拍板
头部采样在请求进入系统的第一站就决定是否采集,决策随上下文一路传播,下游服务"听指挥":不采就不记录。
优点:决策早、开销小——被丢弃的链路全程不产生遥测数据,性能影响几乎为零;实现简单,SDK 内置概率采样器开箱即用。
缺点:决策是盲目的。入口时谁也不知道这个请求会不会在第八跳报错、会不会慢到突破 SLO。用 10% 概率头部采样,错误链路也只有 10% 被留下——恰恰是你最需要的那些。
尾部采样:看清结果再决定
尾部采样等链路执行完毕,拿到全貌(有没有错误、耗时多少、走了哪些服务)再做决策,通常由 Collector 先缓存 Span、再按策略筛选:
- 保留所有含 5xx 错误的链路;
- 保留耗时超过 SLO 阈值的慢链路;
- 对核心业务路径提高保留比例;
- 付费客户的链路多留,免费用户的少留。
优点:决策有依据,该留的一条不丢。
代价:所有 Span 得先收集缓存起来(内存开销),且同一条 Trace 的 Span 必须汇聚到同一个 Collector 实例才能拼出"完整链路"做判断——这要求按 Trace ID 做一致性路由,多实例部署时复杂度显著上升。
OpenTelemetry 中如何配置采样?
头部采样在 SDK 侧一行配置搞定:
from opentelemetry.sdk.trace.sampling import TraceIdRatioBased
# 采样 25%
sampler = TraceIdRatioBased(0.25)
也支持父级采样(ParentBased,跟随上游决策,微服务场景必选)、采样率按环境变量 OTEL_TRACES_SAMPLER 动态调整。
尾部采样在 Collector 配置:
processors:
tail_sampling:
decision_wait: 10s # 等待链路完整的时长
num_traces: 50000 # 缓存容量
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: 10}
策略按序评估:错误全留、慢的全留,剩下的按 10% 保底——兼顾排障需求与整体趋势统计。
尾部采样的落地难点
除了汇聚路由问题,还有两点要留意:decision_wait 设太短会误判未完成的链路,设太长则内存膨胀;缓存溢出时 Collector 会被迫提前决策,可能丢弃本应保留的链路。生产部署需要给采样实例留足内存并监控其丢弃指标。
观测云落地:用观测云控住链路成本
观测云支持以 DataKit 为采集入口的完整采样链路:应用侧用 SDK 做头部采样快速生效;需要精细控制时,在链路进入观测云前经由 OTel Collector 的 tail_sampling 处理器按策略筛选,再通过 OTLP 上报。
落地建议分三步走:
- 起步:全量接入观测云 APM,先用一周摸清真实数据量与成本基线;
- 控量:对高频低价值接口(健康检查、静态资源)在 SDK 侧直接过滤;
- 精细化:错误与慢链路全留、健康链路按比例保底,在观测云的事件中心与监控器中验证——告警命中率不下降,说明采样策略没有伤到排障能力。
常见问题(FAQ)
Q:采样会不会影响指标统计的准确性? 不会。指标(QPS、错误率、延迟分位数)应在采样之前基于全量数据聚合——这正是"先出指标、再采链路"是标准做法的原因。
Q:头部采样率改起来麻烦吗? 用环境变量配置即可动态调整,无需改代码;也可借助采样配置中心方案集中管理。
Q:尾部采样需要多少内存? 取决于 QPS 与 decision_wait:峰值 Span 速率 × 等待时长 × 单 Span 大小,再留 50% 余量。官方建议从 num_traces 上限反推容量规划。
Q:网关层已经做了采样,应用内还要采吗? 建议统一在链路最上游决策(配合 ParentBased 采样器),多层各自采样会导致链路残缺——上游没采下游采了,拼不出完整 Trace。