Micrometer Tracing 链路追踪如何实现?traceId 如何与日志关联?

结论先行:链路追踪把一次跨服务请求串成一颗调用树:全局唯一 traceId + 每跳一个 spanId,通过 HTTP 头(W3C traceparent 等)在服务间传播。Spring Boot 3 用 Micrometer Tracing + Observation API 实现(Sleuth 已停更并入 Micrometer):自动埋点 HTTP 客户端/服务端、数据库与消息,再交给 Brave/OpenTelemetry 上报 Zipkin 等后端;日志侧把 traceId/spanId 放入 MDC 即可实现“日志按链路检索”。

一、核心模型与接入

术语含义
Trace一次完整请求,全局唯一 traceId
Span一次服务调用/内部操作,含 spanId 与父子关系
Propagation跨进程传递上下文(W3C traceparent / B3)
Reporter把 span 上报 Zipkin/OTLP(Jaeger 等)
<!-- 依赖示例 -->
<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
  <groupId>io.zipkin.reporter2</groupId>
  <artifactId>zipkin-reporter-brave</artifactId>
</dependency>
management:
  tracing:
    sampling:
      probability: 1.0          # 采样率,生产可 0.1
  zipkin:
    tracing:
      endpoint: http://zipkin:9411/api/v2/spans
  • 自动生效:RestTemplate/WebClient/Feign、MVC 服务端、JDBC 等由 Observation API 自动埋点;
  • Sleuth 历史:Spring Cloud Sleuth 已归档(spring-attic),Boot 3 起官方链路方案是 Micrometer Tracing + Observation API,依赖坐标与配置完全不同。

二、日志关联 traceId

logging:
  pattern:
    level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"  # MDC 注入
log.info("下单处理中"); // 输出形如 INFO [order-service,abc123...,def456...] 下单处理中
  • 原理:观测系统把当前 traceId/spanId 写入 MDC(ThreadLocal),logback pattern 里用 %X{traceId} 打印;
  • 注意线程切换:@Async/线程池内的 MDC 默认不继承,需手动传递上下文(TaskDecorator 包装)或确认框架已传播;
  • 落库/告警侧:日志平台按 traceId 聚合,出问题可从入口一路查到最深调用。

三、实践要点

  • 采样策略:全量采样数据量大,通常按流量比例/错误请求额外采样;
  • 透传头别丢:网关入口生成 traceId,Feign/MQ 生产消费都要传播上下文,否则链路断裂;
  • 自定义埋点:业务关键路径可用 @Observed/@WithSpan 或手动 Tracer 创建 span 记录耗时与结果。

常见追问 / 记忆点

  • 追问:traceId 从哪来?答:入口(网关/首个服务)生成并注入传播头,下游解析头沿用同一 traceId。
  • 追问:日志里没有 traceId 常见原因?答:未加 MDC pattern、异步线程没传递上下文、或采样导致该请求未被观测。
  • 记忆点:traceId 串全程、spanId 标单跳、头传播靠 W3C、日志关联靠 MDC;异步记得传上下文。
笔记加载中…