链路追踪是分布式系统中快速定位问题和分析性能的重要工具,能够追踪请求在多个服务之间的调用链路:
核心概念:
1. Trace(追踪)
- 一次完整的请求调用链路
- 从客户端发起请求到最终响应的整个过程
- 包含多个 Span
2. Span(跨度)
- 一次具体的调用操作
- 包含开始时间、结束时间、操作名称等
- Span 之间通过父子关系形成调用树
3. Span ID
- 唯一标识一个 Span
- 用于构建调用链路
4. Trace ID
- 唯一标识一次完整的追踪
- 所有相关 Span 共享同一个 Trace ID
5. Parent Span ID
- 标识当前 Span 的父 Span
- 用于构建调用层次关系
6. Annotation(注解)
- 记录关键事件的时间点
- 如 CS(Client Send)、SR(Server Receive)、SS(Server Send)、CR(Client Receive)
7. Baggage(行李)
- 在调用链路中传递的键值对数据
- 用于在服务间传递上下文信息
主流链路追踪工具:
1. Zipkin
- 特点:Twitter 开源,基于 Google Dapper 论文
- 优势:
- 成熟稳定,社区活跃
- 支持多种语言
- 可视化界面友好
- 劣势:
- 存储性能一般
- 功能相对简单
- 适用场景:中小型分布式系统
2. Jaeger
- 特点:Uber 开源,兼容 Zipkin API
- 优势:
- 性能优秀,支持高并发
- 支持多种存储后端
- 功能更完善
- 劣势:
- 相对较新
- 适用场景:高性能要求的分布式系统
3. SkyWalking
- 特点:国产开源,专注于 APM
- 优势:
- 功能全面(链路追踪、性能监控、日志分析)
- 对 Java 支持好
- 中文文档完善
- 劣势:
- 其他语言支持相对较弱
- 适用场景:Java 为主的微服务架构
4. Pinpoint
- 特点:Naver 开源,专注于 Java
- 优势:
- 无代码侵入
- 详细的性能分析
- 劣势:
- 只支持 Java
- 资源占用较高
- 适用场景:Java 单一语言环境
5. OpenTelemetry
- 特点:CNCF 托管,统一的可观测性标准
- 优势:
- 统一的 API 和 SDK
- 多语言支持
- 与多种后端兼容
- 劣势:
- 相对较新,生态还在发展
- 适用场景:需要统一可观测性标准的项目
实现原理:
1. 上下文传递
- 在服务调用时传递 Trace ID 和 Span ID
- 通过 HTTP Header、RPC 元数据等方式传递
- 示例:
java
// gRPC 传递上下文 Context ctx = Context.current().withValue(TRACE_ID_KEY, traceId); stub.withDeadlineAfter(timeout, TimeUnit.MILLISECONDS) .sayHello(request, ctx);
2. 拦截器/过滤器
- 在请求入口和出口拦截
- 记录调用开始和结束时间
- 示例:
java
@Component public class TraceInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String traceId = generateTraceId(); MDC.put("traceId", traceId); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { MDC.remove("traceId"); } }
3. 采样策略
- 固定采样率:按固定比例采样
- 动态采样:根据请求特征动态调整
- 错误优先:优先采样错误请求
4. 数据上报
- 异步上报,避免影响业务性能
- 支持批量上报,减少网络开销
- 支持多种传输协议(HTTP、gRPC、Kafka)
Spring Cloud Sleath 集成示例:
java@SpringBootApplication @EnableZipkinServer public class ZipkinServerApplication { public static void main(String[] args) { SpringApplication.run(ZipkinServerApplication.class, args); } } // 客户端配置 spring: zipkin: base-url: http://localhost:9411 sleuth: sampler: probability: 0.1 # 采样率 10%
使用场景:
1. 性能分析
- 识别慢查询和慢服务
- 分析调用链路中的性能瓶颈
- 优化系统性能
2. 故障排查
- 快速定位问题服务
- 追踪错误传播路径
- 分析故障根因
3. 依赖分析
- 了解服务间依赖关系
- 识别不合理的调用
- 优化服务架构
4. 容量规划
- 分析系统负载分布
- 预测资源需求
- 优化资源配置
最佳实践:
- 合理设置采样率,平衡性能和可观测性
- 结合日志和监控,形成完整的可观测性体系
- 定期分析链路数据,优化系统性能
- 使用统一的 Trace ID,方便跨系统追踪
- 注意敏感信息保护,避免在链路中传递敏感数据