4. 固定采样率配置:AlwaysOn、AlwaysOff、Ratio-based Sampler 的配置与适用场景

固定采样率是 OpenTelemetry 采样策略中最基础、最直接的一类。它不依赖请求属性、不分析链路拓扑,仅根据预设的布尔值或概率决定是否保留 Span。在生产环境中,固定采样率通常用于边界控制(全量采集或完全关闭)以及均匀降噪(按比例丢弃)。

本章将深入剖析三种内置 Sampler 的配置方法、行为差异及典型适用场景,并给出可复用的代码示例。

4.1 三种 Sampler 核心对比

Sampler 名称 决策逻辑 采样率 典型场景
AlwaysOnSampler 始终返回 RECORD_AND_SAMPLE 100% 调试环境、关键链路全量追踪、短期性能剖析
AlwaysOffSampler 始终返回 DROP 0% 关闭追踪、压测时不产生 Span、临时禁用
TraceIdRatioBasedSampler 基于 TraceId 哈希与阈值比较 0.0 ~ 1.0 可配 生产环境均匀降采样、成本控制、长期基线采集
关键认知: AlwaysOn 和 AlwaysOff 是确定性采样,不产生额外计算开销;Ratio-based 需要计算 TraceId 哈希,但开销极低(纳秒级),适合高吞吐场景。

4.2 AlwaysOnSampler:全量采集

当需要不丢失任何一条 Span 时使用。典型场景包括:

  • 开发/测试环境全链路调试
  • 上线前的全量回归验证
  • 短时间(如 5 分钟)的深度性能剖析

Java SDK 配置示例:

// 通过代码设置
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
    .setSampler(Sampler.alwaysOn())
    .build();

// 或通过环境变量(优先级低于代码设置)
// OTEL_TRACES_SAMPLER=always_on

Python SDK 配置示例:

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.sampling import ALWAYS_ON

provider = TracerProvider(sampler=ALWAYS_ON)
生产警告: AlwaysOn 在高 QPS(如 > 10,000/s)下会瞬间产生海量 Span,导致 Export 压力、存储成本飙升。务必配合限流或仅在低流量时段使用。

4.3 AlwaysOffSampler:完全关闭

当需要彻底关闭追踪时使用。典型场景:

  • 压测/基准测试时避免追踪干扰
  • 临时禁用追踪以排查 Exporter 问题
  • 对非关键服务永久关闭(节省资源)

Java SDK 配置示例:

SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
    .setSampler(Sampler.alwaysOff())
    .build();

// 环境变量
// OTEL_TRACES_SAMPLER=always_off

Go SDK 配置示例:

import (
    "go.opentelemetry.io/otel/sdk/trace"
)

tp := trace.NewTracerProvider(
    trace.WithSampler(trace.AlwaysOff()),
)
注意: AlwaysOff 会丢弃所有 Span,包括根 Span。如果只想丢弃部分子 Span,应使用其他 Sampler 或自定义 Sampler。

4.4 TraceIdRatioBasedSampler:按比例均匀采样

这是生产环境最常用的固定采样策略。它根据 TraceId 的哈希值决定是否采样,保证同一个 Trace 的所有 Span 被一致地采样或丢弃。

配置参数:

参数 类型 说明
ratio double (0.0 ~ 1.0) 采样比例。0.25 表示 25% 的 Trace 被采样
seed(部分实现) int 哈希种子,用于多服务间一致性(非标准参数)

Java SDK 配置示例:

// 采样 10% 的 Trace
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
    .setSampler(Sampler.traceIdRatioBased(0.1))
    .build();

// 环境变量
// OTEL_TRACES_SAMPLER=traceidratio
// OTEL_TRACES_SAMPLER_ARG=0.1

Python SDK 配置示例:

from opentelemetry.sdk.trace.sampling import TraceIdRatioBased

provider = TracerProvider(
    sampler=TraceIdRatioBased(rate=0.1)
)

4.5 采样决策流程(SVG 图)

下图展示了固定采样率在 OpenTelemetry SDK 中的完整决策路径:

固定采样率决策流程 Span 创建请求 Sampler 类型 AlwaysOn AlwaysOff TraceIdRatioBased TraceId 哈希 > 阈值? 采样 丢弃 说明 AlwaysOn/AlwaysOff 直接返回决策;Ratio-based 需计算 TraceId 哈希并与阈值比较。

4.6 适用场景速查表

场景 推荐 Sampler 理由
本地开发调试 AlwaysOn 不丢失任何链路,快速定位问题
CI/CD 集成测试 AlwaysOn 确保测试覆盖所有追踪路径
生产环境长期监控 TraceIdRatioBased (0.01~0.1) 控制成本,保留代表性样本
压测/性能基准 AlwaysOff 消除追踪开销,获得真实性能数据
临时故障排查 AlwaysOn(短时) 全量采集后切换回 Ratio 模式
非核心服务 AlwaysOff 或极低 Ratio 节省资源,仅保留关键错误链路

4.7 配置注意事项

  • 环境变量优先级: 代码中显式设置的 Sampler 优先级高于 OTEL_TRACES_SAMPLER 环境变量。
  • 多服务一致性: Ratio-based Sampler 依赖 TraceId 哈希,只要所有服务使用相同的 TraceId(通过传播),采样决策就是一致的。
  • 动态调整: 固定采样率不支持运行时动态变更。如需动态调整,应使用 Sampler 接口的自定义实现或配合配置中心。
  • 采样率精度: 对于极低采样率(如 0.001),建议使用 TraceIdRatioBased 而非自定义 Sampler,避免哈希分布不均匀。
最佳实践: 生产环境推荐从 0.1(10%)开始,根据存储预算和查询需求逐步调整。对于高流量服务(QPS > 100,000),0.01(1%)通常已足够。