链路追踪
问题
微服务架构中如何实现链路追踪?Spring Cloud 的链路追踪方案有哪些?
答案
为什么需要链路追踪
一次用户请求可能经过多个微服务。当出现性能问题或错误时,需要知道请求经过了哪些服务、每个环节耗时多少、在哪里出了问题。
核心概念
| 概念 | 说明 |
|---|---|
| Trace | 一次完整的请求链路(全局唯一 TraceId) |
| Span | 链路中的一个操作单元(服务调用、数据库查询) |
| TraceId | 全局唯一标识,贯穿整条调用链 |
| SpanId | 当前操作的标识 |
| ParentSpanId | 父操作标识(用于构建调用树) |
Spring Cloud 链路追踪方案
| 方案 | 说明 | 状态 |
|---|---|---|
| Spring Cloud Sleuth | Spring 官方,自动埋点 | 已废弃(2022.x 后移除) |
| Micrometer Tracing | Sleuth 的继任者,Spring Boot 3 标准 | 推荐 |
| SkyWalking | Apache 开源,Java Agent 无侵入 | 生产广泛使用 |
| Zipkin | Twitter 开源,轻量级 | 适合小型项目 |
| Jaeger | Uber 开源,云原生 | CNCF 毕业项目 |
Micrometer Tracing + Zipkin
<!-- Micrometer Tracing(Bridge 选择 Brave 或 OpenTelemetry)-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<!-- Zipkin 上报 -->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
management:
tracing:
sampling:
probability: 1.0 # 采样率(1.0 = 100%,生产建议 0.1)
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans
logging:
pattern:
# 日志中自动包含 traceId 和 spanId
level: "%5p [${spring.application.name},%X{traceId},%X{spanId}]"
日志输出示例:
INFO [order-service,abc123def456,s2a3b4c5] c.e.OrderController : 创建订单
INFO [user-service,abc123def456,s6d7e8f9] c.e.UserController : 查询用户
SkyWalking(无侵入方案)
SkyWalking 通过 Java Agent 字节码增强,无需修改任何代码:
# 启动时添加 Agent
java -javaagent:/path/to/skywalking-agent.jar \
-Dskywalking.agent.service_name=order-service \
-Dskywalking.collector.backend_service=localhost:11800 \
-jar app.jar
链路追踪架构
TraceId 传递机制
链路追踪的关键是 TraceId 需要在服务间传递:
| 调用方式 | 传递方式 |
|---|---|
| HTTP(Feign/RestTemplate) | 通过 HTTP Header(X-B3-TraceId) |
| 消息队列(Kafka/RabbitMQ) | 通过消息 Header |
| 线程池/异步 | 需要特殊处理(装饰器包装) |
默认情况下 TraceId 存储在 ThreadLocal 中,跨线程(线程池、@Async)时会丢失。解决方案:
- 使用增强的
TaskDecorator传递上下文 - SkyWalking Agent 自动处理
- Micrometer Tracing 提供
ContextExecutorService
常见面试问题
Q1: 链路追踪的原理?
答案:
核心原理是上下文传播。入口服务生成全局唯一的 TraceId,每个服务调用创建一个 Span(包含 SpanId、ParentSpanId、耗时等信息)。TraceId 通过 HTTP Header 或消息 Header 传递给下游服务。各服务将 Span 数据异步上报到收集器,最终在可视化面板上还原完整调用链。
Q2: Sleuth 和 Micrometer Tracing 的关系?
答案:
Spring Cloud Sleuth 是 Spring Cloud 2022.x 之前的链路追踪方案。从 Spring Boot 3 开始,Sleuth 被 Micrometer Tracing 取代。Micrometer Tracing 是更通用的追踪门面,支持 Brave(Zipkin)和 OpenTelemetry 两种追踪实现,API 更标准化。
Q3: 采样率如何设置?
答案:
生产环境不建议 100% 采样(性能开销大),一般设置 10%~20%。对于关键业务(支付、下单)可以提高采样率。通过 management.tracing.sampling.probability 配置。也可以使用自定义采样器(如异常请求 100% 采样)。
Q4: SkyWalking 和 Zipkin 怎么选?
答案:
- Zipkin:轻量级,学习成本低,适合小型项目或 Spring Cloud 全家桶
- SkyWalking:功能丰富(链路、指标、日志、告警),Java Agent 无侵入,支持更多语言,适合大型生产环境
如果已经使用 Spring Cloud 全家桶,Zipkin 更轻量;如果需要全面的 APM 方案,选 SkyWalking。
相关链接
- Micrometer Tracing 文档
- Zipkin 官网
- SkyWalking 官网
- 服务网关 - 链路追踪从网关开始
- 远程调用 - Feign 自动传递 TraceId