4. 追踪数据采集:自动埋点与手动埋点策略、Agent 与 SDK 部署模式、采样策略

分布式追踪的数据采集是整个可观测性体系的“第一公里”。采集策略的优劣直接决定了故障排查时能否拿到有效数据,以及存储成本是否可控。本章从埋点方式、部署模式、采样策略三个维度展开,帮助值班台工程师在实战中做出合理选择。

4.1 自动埋点与手动埋点策略

埋点(Instrumentation)是将追踪代码注入应用程序的过程。根据注入方式的不同,分为自动埋点和手动埋点两大类。

对比维度 自动埋点 手动埋点
实现方式 通过字节码增强、AOP、中间件钩子自动注入 开发者在代码中显式调用 SDK API
侵入性 零代码侵入,无需修改业务代码 高侵入,需要修改源码并重新编译
覆盖范围 HTTP、gRPC、数据库、消息队列等通用组件 业务自定义逻辑、关键路径、事务边界
上下文丰富度 基础链路信息(耗时、状态码、请求大小) 可携带业务标签、用户ID、订单号等语义信息
部署成本 低,通常通过 Agent 或启动参数一键接入 高,需要开发团队投入持续维护
典型场景 快速接入、存量系统、第三方组件 核心交易链路、自定义异步流程、错误诊断
值班台建议:推荐采用“自动埋点为主 + 手动埋点补充”的混合策略。自动埋点保证基础链路全覆盖,手动埋点用于关键业务路径和故障高发区域,避免过度埋点导致性能开销失控。
自动埋点与手动埋点混合策略架构 应用服务 (Java / Go / Python / Node.js) 业务逻辑层 自动埋点层 字节码增强 / AOP / 中间件钩子 手动埋点层 SDK API / 业务标签 / 自定义 Span Span 数据汇聚与导出 统一 Span 格式 → 采样 → 上报

4.2 Agent 与 SDK 部署模式

部署模式决定了追踪能力如何交付到目标服务中。主流方案分为 Agent 模式和 SDK 模式,两者在运维复杂度、资源隔离、版本管理上存在显著差异。

4.2.1 Agent 模式

  • 原理:以独立进程或 sidecar 形式部署,通过字节码增强或网络代理劫持应用流量。
  • 优势:应用无感知,升级 Agent 无需重启业务进程;支持多语言统一管理。
  • 劣势:额外资源开销(CPU/内存);对 Agent 稳定性要求高,故障可能影响宿主。
  • 典型实现:Java Agent(如 OpenTelemetry Java Agent)、eBPF 内核级 Agent。

4.2.2 SDK 模式

  • 原理:将追踪库以依赖形式引入应用代码,编译时链接。
  • 优势:资源开销可控,与应用进程共享生命周期;可精细控制埋点行为。
  • 劣势:升级 SDK 需要重新编译部署;多语言版本管理复杂。
  • 典型实现:OpenTelemetry SDK、Jaeger Client、Zipkin Brave。
对比维度 Agent 模式 SDK 模式
部署方式 独立进程 / sidecar / 内核模块 代码依赖 / 编译时引入
升级影响 热升级,无需重启应用 需重新编译部署
资源隔离 独立进程,可单独限流 与应用共享资源
语言支持 通常绑定特定语言或内核 多语言 SDK 独立维护
故障影响面 Agent 崩溃可能影响应用 SDK 异常仅影响当前进程
适用场景 大规模集群、存量系统、快速接入 核心链路、精细控制、资源敏感
值班台避坑:Agent 模式虽然运维友好,但在高并发场景下需关注 Agent 自身的 CPU 和内存开销。建议为 Agent 设置独立的资源限制(如 cgroup),并配置熔断机制——当 Agent 处理延迟超过阈值时自动降级,避免 Agent 故障拖垮业务进程。
Agent 与 SDK 部署模式对比 Agent 模式 业务进程 应用代码 Agent 进程 字节码增强 Span 导出器 OTLP / Jaeger / Zipkin SDK 模式 业务进程(内嵌 SDK) 应用代码 + 追踪 SDK Span 导出器 OTLP / Jaeger / Zipkin

4.3 采样策略

在高吞吐分布式系统中,全量采集所有 Span 会产生海量数据,导致存储成本爆炸和查询性能下降。采样策略是平衡数据完整性与成本的关键手段。

4.3.1 头采样(Head Sampling)

在请求入口处(Trace 起始端)决定是否采样。一旦决定,整个 Trace 的所有 Span 要么全部采集,要么全部丢弃。

  • 优点:实现简单,决策点单一,适合固定采样率场景。
  • 缺点:无法根据请求执行过程中的特征(如错误、延迟)动态调整;低概率采样时容易丢失异常链路。
  • 典型实现:固定概率采样(如 1%)、速率限制采样(每秒 N 条 Trace)。

4.3.2 尾采样(Tail Sampling)

先采集所有 Span 到本地缓冲区,待 Trace 结束后根据完整特征(是否包含错误、延迟是否超阈值、特定标签)决定是否保留。

  • 优点:可基于完整 Trace 信息做决策,确保异常链路 100% 保留;支持复杂策略(如错误优先、慢调用优先)。
  • 缺点:需要额外缓冲区存储,增加延迟和资源开销;实现复杂度高。
  • 典型实现:OpenTelemetry Collector 的 tail_sampling 处理器、Jaeger 的尾部采样策略。

4.3.3 概率采样(Probabilistic Sampling)

基于 Trace ID 的哈希值或随机数,按固定概率决定是否采样。可独立应用于每个 Span,也可用于 Trace 级别。

  • 优点:计算开销极低,适合超大规模集群;无状态,易于水平扩展。
  • 缺点:无法感知请求内容,可能丢失关键异常链路。
  • 典型实现:Trace ID 取模、随机数比较。
对比维度 头采样 尾采样 概率采样
决策时机 Trace 起始 Trace 结束 Span 生成时
决策依据 固定规则 / 速率 完整 Trace 特征 随机 / 哈希
异常链路保留 低概率下易丢失 可 100% 保留 随机丢失
资源开销 低 高(需缓冲区) 极低
实现复杂度 低 高 极低
适用场景 稳定流量、成本敏感 核心链路、故障诊断 大规模、无状态
值班台最佳实践:推荐采用“分层采样”策略——核心交易链路使用尾采样(100% 保留错误和慢 Trace),非核心链路使用概率采样(1%~5%),边缘服务使用头采样(固定 0.1%)。同时设置全局速率上限,防止突发流量冲垮后端存储。
三种采样策略决策流程对比 头采样 请求到达入口 采样决策(固定概率) 采集整个 Trace 丢弃整个 Trace 尾采样 采集所有 Span 本地缓冲区暂存 Trace 结束后决策 保留 / 丢弃 概率采样 每个 Span 独立决策 Trace ID 哈希取模 命中则采集 未命中则丢弃

4.4 采样策略组合与值班台实战

单一采样策略无法满足所有场景。值班台工程师需要根据业务重要性和故障排查需求,设计多级采样组合策略。

推荐组合策略(生产环境已验证):
  1. 核心交易链路(支付、下单、登录):尾采样 + 错误/慢 Trace 100% 保留 + 正常 Trace 10% 概率采样。
  2. 重要业务链路(搜索、推荐、消息):头采样 + 固定 5% 概率 + 速率限制 1000 Trace/s。
  3. 边缘服务(日志、监控、配置):概率采样 + 0.1% 固定概率。
  4. 全局兜底:所有服务配置最大速率上限(如 5000 Span/s),防止突发流量打爆 Collector。
# OpenTelemetry Collector 尾采样配置示例
processors:
  tail_sampling:
    decision_wait: 30s          # 等待 Trace 结束的最长时间
    num_traces: 100000          # 缓冲区最大 Trace 数
    expected_new_traces_per_sec: 1000
    policies:
      - name: error-policy
        type: status_code
        status_code: { status_codes: [ERROR] }
      - name: slow-policy
        type: latency
        latency: { threshold_ms: 5000 }
      - name: probabilistic-policy
        type: probabilistic
        probabilistic: { sampling_percentage: 10 }
值班台检查清单:
  • 确认采样策略是否覆盖了所有核心故障场景(错误、超时、高延迟)。
  • 检查采样率是否与存储容量匹配(建议预留 30% 存储余量)。
  • 验证采样决策是否在 Collector 层面生效,避免 Agent 端重复采样。
  • 定期审计采样数据,确保异常链路未被遗漏。