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;异步记得传上下文。