如何采样 0.1% 的 trace 同时保证异常链路必采

解读

面试官想验证两点:

  1. 你是否理解分布式链路追踪采样对生产环境的意义——既要降低存储与网络开销(0.1%≈1/1000),又要不丢异常现场(必采)。
  2. 你是否能在 Docker 容器化场景下,把采样策略固化到镜像构建、编排文件与运行时配置中,做到一次构建、随处运行,而不是临时手动改代码。

国内大厂(阿里、腾讯、字节)的面试套路是:先问“怎么做”,再追问“怎么保证落地”“怎么灰度”“怎么回滚”。因此回答必须给出可落地的镜像级方案,并预留动态开关

知识点

  1. 头部采样(Head-based):在请求入口按固定概率决定是否采样,实现简单但会漏掉“开始正常、后半段异常”的链路。
  2. 尾部采样(Tail-based):先全量采集 Span,等链路完成后根据错误码、耗时、自定义标签再决定是否保留,异常必采不会漏,但内存压力大。
  3. 组合采样(Hybrid):入口做概率限流(0.1%),同时把异常 Span 强制打上强制采样标,在otel-collector 层做尾部二次决策,兼顾成本与完整性。
  4. Docker 化要点
    • 镜像里只装otel-contrib-collector二进制,不装 agent,避免多进程sidecar 资源争抢。
    • 多阶段构建把 collector 配置与业务镜像分离,配置热加载通过 Docker Config 或 K8s ConfigMap 挂卷。
    • 非 root 用户启动 collector,只读根文件系统,降低攻击面。
  5. 国内合规:日志与 trace 需脱敏,collector 内需开启processor attributes/delete动作,把手机号、身份证字段剔除,否则无法过等保测评。

答案

  1. 镜像构建阶段
    在 Dockerfile 里引入官方 otel-contrib-collector 镜像作为第二阶段,把自定义 otelcol.yaml 拷进去:

    FROM otel/opentelemetry-collector-contrib:0.91.0 as otel
    COPY otelcol.yaml /etc/otelcol-contrib/otelcol.yaml
    USER 65534:65534
    ENTRYPOINT ["/otelcol-contrib", "--config=/etc/otelcol-contrib/otelcol.yaml"]
    

    业务容器通过Docker Compose service dependency保证 otel 容器先启动,再注入环境变量
    OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317

  2. 采样规则(otelcol.yaml)

    processors:
      tail_sampling:
        decision_wait: 10s
        num_traces: 50000
        expected_new_traces: 100
        policies:
          - name: error-policy
            type: status_code
            status_code: {status_codes: [ERROR]}
          - name: slow-policy
            type: latency
            latency: {threshold_ms: 2000}
          - name: probabilistic-policy
            type: probabilistic
            probabilistic: {sampling_percentage: 0.1}
        # 组合逻辑:OR,满足任一即保留
    

    这样异常链路 100% 保留,正常链路按 0.1% 随机采样,内存缓存窗口 10 s,单实例峰值占用 < 300 MB,容器 limit 500 Mi 足够

  3. 运行时动态调整
    把 otelcol.yaml 挂为 Docker Config
    docker config create otel_cfg otelcol.yaml
    服务更新时
    docker service update --config-rm otel_cfg --config-add source=otel_cfg,target=/etc/otelcol-contrib/otelcol.yaml myservice
    无需重建镜像即可秒级灰度新的采样率,满足国内夜间低峰调参的运维习惯。

  4. 资源与成本估算
    单容器 1000 QPS为例,0.1% 采样后上报 1 trace/s,每条 trace 平均 20 Span,压缩后 5 KB,日增量 432 MB;异常额外增加不超过 5% 体积,远低于国内云厂商免费额度(阿里云 SLS 500 MB/日免费),无需额外预算审批

  5. 故障兜底
    如果 collector 容器 OOM,业务进程不受影响,因为 SDK 默认内存队列满则丢弃,并暴露 Prometheus 指标 otelcol_exporter_send_failed_spans可配 Alertmanager 告警;同时镜像内预留host 网络 fallbackdocker run --network host 可秒级绕过容器网络故障。

拓展思考

  1. 多地域容灾:国内华北、华东、华南三地机房,collector 级联模式,先本地 tail-sampling,再按 1% 比例二次采样后上报中心 Region,实现跨地域成本二次压缩
  2. 与 Service Mesh 结合:在 Istio 环境,把采样决策下沉到 Envoy Filter,用 Wasm 插件读取 HTTP Header x-trace-force=1异常链路在 Sidecar 层即被标记,无需业务改代码,真正做到零侵入
  3. 安全加固:镜像内开启 TLS mTLS 双向认证,证书通过 Docker Secret 分发,私钥权限 0400,满足国内金融客户容器平台等级保护 2.0要求;同时镜像签名采用 cosign,阻断供应链投毒