全链路追踪怎么做?traceId、span 与日志体系如何打通?

结论先行:全链路追踪把一次请求的跨服务调用组织成一棵树:traceId 标识整条链路,spanId 标识其中一次调用(含父 span),按时间与父子关系还原调用瀑布。价值一半在追踪数据,另一半在与日志打通——让 traceId 贯穿日志,出问题能一条链拉出全部日志。

一、核心概念

概念含义例子
trace一次完整请求用户下单的整条链路
traceId链路唯一 id全局透传,日志关联键
span一次 RPC/DB/本地调用网关到订单服务的调用
spanId / parentSpanId本调用与父调用组成树形结构
trace: 6d6e…
├─ span A  网关 -> 订单服务   5ms
│  ├─ span B  订单 -> DB       2ms
│  └─ span C  订单 -> MQ       1ms
└─ span D  库存服务消费事件    4ms

二、traceId 怎么传

  • 入口(网关/入口服务)生成 traceId,写入约定 Header(如 X-Trace-Id)随 HTTP/RPC/MQ 透传。
  • 中间件统一拦截:从 Header 取或新建 traceId,放入上下文与日志 MDC。
  • 常见的坑:异步线程池、MQ 消费要手动传递上下文,否则 trace 断链。

三、与日志体系打通

// 日志里带上 traceId(如 logback 的 MDC)
MDC.put("traceId", traceId);
log.info("扣减库存开始");
  • 约定:所有应用日志行都打印 traceId,采集到 ELK/Loki 后可按 traceId 聚合一次请求的全部日志。
  • 自查标准:没有 traceId 的日志行等于离线日志,无法串联,要在埋点规范上卡住。

四、方案与采样

  • 开源选型:SkyWalking(自研探针 + UI)、Zipkin/Jaeger(OpenTelemetry 生态)。
  • 采样策略:高价值接口全量采样 + 普通接口按比例采样(如 10%)+ 错误链路强制采样。

常见追问与记忆点

  • 追问:追踪系统本身挂了会影响业务吗?探针必须旁路:异步上报、失败静默,绝不阻塞主链路。
  • 追问:怎么快速定位慢在哪?看 trace 瀑布里耗时占比最大的 span,结合日志与指标下钻。
  • 记忆点:traceId 贯穿链路、span 组织调用树;追踪的价值 = 链路图 + 全链路可检索日志。
笔记加载中…