3. OpenTelemetry 采样基础:Head Sampling 与 Tail Sampling 的核心区别
在 OpenTelemetry 的采样体系中,决策时机是区分不同采样策略的核心维度。根据采样决策是在 Span 创建之初(头部)还是在 Span 完成并收集到所有属性之后(尾部),采样被划分为 Head Sampling(头部采样) 与 Tail Sampling(尾部采样)。这两种策略在延迟、准确性、资源消耗和适用场景上存在本质差异,直接影响 SLI 的统计可靠性。
3.1 Head Sampling:快速决策,低延迟
Head Sampling 在 Span 被创建时立即做出采样决策,无需等待 Span 结束或收集后续属性。决策依据通常仅基于 Span 的固定属性(如 Span Name、Service Name、预定义的采样率)。
核心特征: 决策点位于 Trace 生命周期的起点,一旦决定,整个 Trace 的所有 Span 要么全部保留,要么全部丢弃(基于 TraceId 的一致性哈希)。
3.1.1 工作原理
- Span 创建:应用代码开始一个 Span,生成 TraceId 和 SpanId。
- 采样器介入:OpenTelemetry SDK 中的
Sampler接口被调用,传入 TraceId、Span 名称、Span 属性等。 - 决策返回:采样器返回
Decision(DROP或RECORD_AND_SAMPLE)。 - 传播:决策结果通过 W3C TraceContext 传播到下游服务,确保同一 Trace 的所有 Span 采样决策一致。
3.1.2 典型实现:TraceIdRatioBased Sampler
// OpenTelemetry Java SDK 配置示例
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
.setSampler(Sampler.traceIdRatioBased(0.1)) // 10% 采样率
.build();
3.2 Tail Sampling:精准决策,高保真
Tail Sampling 在 Span 完成并收集到所有属性、状态码、事件和异常信息之后,由独立的采样处理器(通常运行在 Collector 端)做出决策。决策依据可以包含 Span 的完整上下文,如错误状态、延迟、特定属性值等。
关键优势: Tail Sampling 可以基于“结果”做决策,例如只保留包含错误的 Trace,或只保留延迟超过 P99 阈值的 Trace,从而大幅提升 SLI 相关数据的准确性。
3.2.1 工作原理
- Span 完成:所有 Span 数据(包括属性、事件、状态)被完整导出到 Collector。
- Trace 组装:Collector 中的
TailSamplingProcessor根据 TraceId 将属于同一 Trace 的所有 Span 缓存并组装成完整 Trace。 - 策略评估:处理器依次评估用户配置的采样策略(如
ErrorSampler、LatencySampler、AndCompositeSampler)。 - 决策执行:满足策略条件的 Trace 被保留并发送到后端;不满足的 Trace 被丢弃。
3.3 核心区别对比
| 对比维度 | Head Sampling | Tail Sampling |
|---|---|---|
| 决策时机 | Span 创建时(Trace 起点) | Span 完成后(Trace 终点) |
| 决策依据 | TraceId、Span 名称、固定属性 | 完整 Span 属性、状态码、延迟、错误信息 |
| 延迟影响 | 无额外延迟(同步决策) | 引入缓存和等待延迟(异步决策) |
| 内存开销 | 低(无状态) | 高(需要在 Collector 中缓存 Trace) |
| SLI 准确性 | 低(无法区分错误/慢 Trace) | 高(可精准保留关键 Trace) |
| 配置复杂度 | 简单(仅需采样率) | 复杂(需定义策略、超时、缓存大小) |
| 适用场景 | 高吞吐、低延迟、通用监控 | 错误分析、延迟分析、SLI 保真 |
3.4 架构对比图
下图展示了 Head Sampling 与 Tail Sampling 在数据流路径上的核心差异。Head Sampling 在应用端快速决策,而 Tail Sampling 在 Collector 端进行二次筛选。
3.5 对 SLI 准确性的影响分析
采样策略的选择直接决定了 SLI 计算中使用的数据样本是否具有代表性。以下是两种策略对常见 SLI 指标的影响:
- 错误率 SLI:Head Sampling 可能因随机丢弃而遗漏关键错误 Trace,导致错误率被低估;Tail Sampling 可通过
ErrorSampler确保所有错误 Trace 被保留,错误率计算更准确。 - 延迟 SLI(P99/P95):Head Sampling 的随机性可能使高延迟 Trace 被丢弃,导致延迟指标被低估;Tail Sampling 的
LatencySampler可专门保留慢 Trace,使延迟分布更真实。 - 可用性 SLI:Head Sampling 无法区分正常请求和故障请求,可用性计算偏差较大;Tail Sampling 可基于状态码精准筛选,可用性数据更可靠。
重要提醒: 如果 SLI 目标要求高精度(如 99.9% 可用性监控),必须使用 Tail Sampling 或结合 Head Sampling 与后端二次采样。仅依赖 Head Sampling 可能导致 SLI 数据严重失真,尤其在错误率较低的场景下。
3.6 混合策略:Head + Tail 联合采样
在实际生产环境中,最佳实践通常是 Head Sampling 做第一级粗筛(降低数据量),Tail Sampling 做第二级精筛(保证 SLI 准确性)。这种混合策略兼顾了低延迟和高保真:
# OpenTelemetry Collector 配置示例:Head + Tail 联合采样
receivers:
otlp:
protocols:
grpc:
processors:
# 第一级:Head Sampling(Collector 端模拟,基于 TraceId)
probabilistic_sampler:
hash_seed: 42
sampling_percentage: 20 # 先降低 80% 数据量
# 第二级:Tail Sampling(基于完整 Trace 信息)
tail_sampling:
decision_wait: 10s
num_traces: 10000
expected_new_traces_per_sec: 500
policies:
- name: error-policy
type: status_code
status_code: ERROR
- name: latency-policy
type: latency
threshold_ms: 500
exporters:
otlp:
endpoint: "backend:4317"
service:
pipelines:
traces:
receivers: [otlp]
processors: [probabilistic_sampler, tail_sampling]
exporters: [otlp]
实践建议: 在混合策略中,Head Sampling 的采样率建议设置在 10%-30%,以控制 Collector 的内存压力;Tail Sampling 的策略应优先保留对 SLI 影响最大的 Trace(如错误和慢请求),确保关键数据不丢失。