分布式链路追踪
什么是链路追踪?
在微服务架构中,一个请求可能经过多个服务,链路追踪用于追踪请求的完整调用链路。
请求 → 网关 → 订单服务 → 库存服务 → 数据库
↓
支付服务
↓
通知服务
链路追踪记录:
- 每个服务的处理时间
- 调用关系
- 错误信息核心概念
| 概念 | 说明 |
|---|---|
| Trace | 完整调用链,一个 Trace 包含多个 Span |
| Span | 单个服务的调用,包含开始时间、结束时间、操作名 |
| TraceId | 全局唯一 ID,标识整个调用链 |
| SpanId | 标识单个 Span |
| ParentSpanId | 父 Span 的 ID |
调用链结构
TraceId: abc123
Span A (SpanId: 1, Parent: null)
│
├── Span B (SpanId: 2, Parent: 1)
│ │
│ └── Span D (SpanId: 4, Parent: 2)
│
└── Span C (SpanId: 3, Parent: 1)主流方案
| 方案 | 说明 | 特点 |
|---|---|---|
| SkyWalking | 国产开源 | 无侵入、功能全 |
| Zipkin | Twitter 开源 | 轻量级 |
| Jaeger | Uber 开源 | 云原生 |
| Pinpoint | 韩国开源 | UI 美观 |
SkyWalking
架构
┌─────────────────────────────────────────────────────────────┐
│ SkyWalking OAP │
│ (分析、聚合、存储) │
└─────────────────────────────────────────────────────────────┘
↑ ↑
│ gRPC │ 查询
│ │
┌────────┴────────┐ ┌─────────┴─────────┐
│ SkyWalking │ │ SkyWalking UI │
│ Java Agent │ │ │
│ (无侵入探针) │ │ (可视化界面) │
└────────┬────────┘ └───────────────────┘
│
│ 监控
↓
┌─────────────────────────────────────────────────────────────┐
│ 应用服务 │
│ OrderService → StockService → PaymentService │
└─────────────────────────────────────────────────────────────┘使用方式
1. 下载 Agent
wget https://archive.apache.org/dist/skywalking/java-agent/8.16.0/apache-skywalking-java-agent-8.16.0.tgz
tar -xzf apache-skywalking-java-agent-8.16.0.tgz2. 启动应用(附加 Agent)
java -javaagent:/path/to/skywalking-agent.jar \
-Dskywalking.agent.service_name=order-service \
-Dskywalking.collector.backend_service=localhost:11800 \
-jar order-service.jar3. 访问 UI
http://localhost:8080功能
| 功能 | 说明 |
|---|---|
| 拓扑图 | 服务调用关系可视化 |
| 链路追踪 | 查看单个请求的完整链路 |
| 性能指标 | 响应时间、吞吐量、错误率 |
| 告警 | 性能异常自动告警 |
Spring Cloud Sleuth + Zipkin
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>配置
spring:
sleuth:
sampler:
probability: 1.0 # 采样率 100%
zipkin:
base-url: http://localhost:9411自定义 Span
@Service
public class OrderService {
@Autowired
private Tracer tracer;
public Order createOrder(OrderDTO dto) {
// 创建自定义 Span
Span span = tracer.nextSpan().name("create-order");
try (Tracer.SpanInScope ws = tracer.withSpan(span.start())) {
// 业务逻辑
return doCreateOrder(dto);
} finally {
span.end();
}
}
}日志集成
<!-- logback-spring.xml -->
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%X{traceId},%X{spanId}] [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
</configuration>TraceId 传递
HTTP 传递
请求头:
X-Trace-Id: abc123
X-Span-Id: 1
X-Parent-Span-Id: nullMQ 传递
// 生产者
rabbitTemplate.convertAndSend(queue, message, msg -> {
msg.getMessageProperties().setHeader("X-Trace-Id", traceId);
return msg;
});
// 消费者
@RabbitListener(queues = "order.queue")
public void handle(Message message, @Header("X-Trace-Id") String traceId) {
MDC.put("traceId", traceId);
// 处理业务
MDC.remove("traceId");
}面试高频问题
Q1: 链路追踪的实现原理?
- 在请求入口生成 TraceId
- 通过 HTTP Header / MQ Header 传递 TraceId
- 每个服务创建 Span,记录处理时间
- 异步上报到链路追踪系统
Q2: SkyWalking 和 Zipkin 的区别?
| 对比 | SkyWalking | Zipkin |
|---|---|---|
| 侵入性 | 无(Agent) | 低(依赖) |
| 功能 | 更全面 | 基础 |
| 性能影响 | 低 | 中 |
| 存储 | ES/MySQL 等 | 内存/ES/MySQL |
Q3: 采样率如何设置?
- 开发环境:100%
- 生产环境:10%-50%(根据流量调整)
- 异常请求:100%
Q4: TraceId 如何保证全局唯一?
UUID 或 Snowflake 算法生成。
总结
分布式链路追踪核心要点:
1. 核心概念:Trace、Span、TraceId、SpanId
2. 主流方案:SkyWalking(无侵入)、Zipkin(轻量)
3. 传递方式:HTTP Header、MQ Header
4. 功能:拓扑图、链路追踪、性能指标、告警