上下文传播是什么
追踪的核心是让上下文跟着请求走:同一进程内用上下文对象(如 OpenTelemetry 的 Context 与当前 span)传递,跨进程则要靠协议头承载——HTTP 用 traceparent,gRPC 用 metadata,消息队列用消息头。传播链一旦断开,后续服务就会各自开新 trace,链路图上表现为可疑的多条碎片。
基本信息
| 进程内 | 上下文对象 + 当前 span |
|---|---|
| HTTP | traceparent / tracestate 请求头 |
| gRPC | metadata 键值(拦截器自动注入) |
| 消息队列 | 消息 headers |
| 数据库 | 由客户端埋点库处理(连接级) |
| 相关规范 | W3C Trace Context |
典型使用场景
- 验证 HTTP 调用链是否连成一条完整 trace
- 排查 gRPC 服务间调用为何出现多条独立链路
- 确认消息消费端是否延续了生产端的 trace 上下文
- 为自研 RPC 或中间件补上上下文序列化逻辑
- 统一异步任务(线程池、定时任务)的上下文传递方式
- 排查跨机房调用链路断开时,逐跳核对请求头是否被网关剥离
各协议承载位置
各协议承载位置
HTTP → traceparent / tracestate 请求头
gRPC → metadata 键值(OTEL 拦截器自动注入)
Kafka → 消息 headers
数据库 → 由客户端埋点库负责(连接级)
# 自研 RPC/中间件:显式把上下文序列化进协议字段
# 异步线程池:提交任务时复制上下文,避免子线程丢失父 span
# 验证方法:入口与下游各打一条带 trace_id 的日志,比对是否一致常见断链位置
| 环节 | 断链原因 | 处理方向 |
|---|---|---|
| HTTP 网关 | 剥离未知请求头 | 把 traceparent 加入白名单 |
| gRPC | 未启用拦截器 | 安装并注册 OTEL 拦截器 |
| 消息队列 | 未注入消息头 | 在生产端写入、消费端读取 |
| 自研 RPC | 协议里没放上下文字段 | 显式序列化并透传 |
| 异步线程 | 上下文未复制 | 提交任务时复制上下文 |
验证方法:在入口打一条带 trace_id 的日志,看下游服务日志是否出现同一个 trace_id,最直接也最可靠。
自研协议常被遗漏,链路在自研 RPC 处断掉,接入清单要覆盖全部通信方式(含缓存、任务调度与消息)。
异步队列两端时间跨度大,同一 trace 长时间未结束会让部分后端的聚合视图异常,采样与超时设置要一并考虑。
线程池与响应式框架容易丢上下文:默认情况下子线程不会继承父 span,需要显式复制或使用框架提供的桥接能力。