Spring Cloud Sleuth 链路追踪

1. 链路追踪

在微服务架构中,一个请求可能经过多个服务调用,链路追踪(Distributed Tracing)用于记录请求的完整路径,帮助开发者:

排查问题:快速定位性能瓶颈或错误来源。

监控性能:分析各服务调用耗时。

2. Spring Cloud Sleuth

2.1. 关键术语

术语

说明

Trace

代表一个完整的请求链路,每个 Trace 有唯一的 Trace ID,贯穿整个请求流程。

Span

代表请求链路中的一个基本工作单元(如服务间的一次调用、数据库操作等)。

Span ID

唯一标识一个 Span,在同一个 Trace 中,Span 之间通过父子关系形成树状结构。

Parent ID

标识当前 Span 的父 Span ID,用于构建 Span 树。

Annotation

用于记录事件时间点(如请求开始、结束、异常等),常见类型包括:

- cs(Client Send):客户端发起请求,标志 Span 开始。

- sr(Server Receive):服务端接收请求,计算网络延迟(sr - cs)。

- ss(Server Send):服务端完成处理,将结果返回客户端,计算服务处理时间(ss - sr)。

- cr(Client Receive):客户端接收响应,标志 Span 结束。

2.2. Sleuth 工作流程

Spring Cloud Sleuth 的工作流程可分为 链路创建、跨服务传递、数据采集、数据输出 四个阶段

2.2.1. 链路创建(请求入口)

当请求进入微服务系统(如网关或服务入口)时,Sleuth 会自动生成 Trace ID 和 Root Span(根 Span,Span ID 通常与 Trace ID 一致)。

traceId:a1b2c3d4e5f6   // 全局唯一
spanId: a1b2c3d4e5f6  	// 跟spanId与traceId相同
parentSpanId: null			// 无父span

2.2.2. 跨服务传递(核心机制)

  • HTTP 调用场景
    Sleuth 通过 拦截器(Interceptor) 自动将 Trace ID、Span ID 等元数据注入 HTTP 请求头(默认头名为 X-B3-TraceIdX-B3-SpanIdX-B3-ParentSpanId 等)。

下游服务接收到请求后,解析请求头中的元数据,创建 子 Span(Parent Span ID 为上游 Span 的 ID)。

// 服务 A 调用服务 B 时的请求头
X-B3-TraceId: a1b2c3d4e5f6   // 全局 Trace ID
X-B3-SpanId: 1234abcd         // 服务 A 中当前 Span 的 ID(父 Span ID)
X-B3-ParentSpanId: a1b2c3d4e5f6 // 根 Span ID(仅在非根 Span 中存在)
  • 消息中间件场景(如 RabbitMQ、Kafka)
    Sleuth 通过 消息监听器(Message Listener) 自动提取 / 注入链路元数据到消息头中,确保跨消息服务的链路连续性。

2.2.3. 输出追踪日志

Sleuth 会自动将 Trace ID 和 Span ID 注入应用日志,方便通过日志关联链路数据,核心实现如下:

  • MDC(Mapped Diagnostic Context):

在创建 Span 时,将 traceId 和 spanId 存入 MDC。

日志框架(如 Logback、Log4j)通过配置 %X{traceId}、%X{spanId} 输出这些值。

// 日志格式:
[%d{yyyy-MM-dd HH:mm:ss}]|%-5p|[%X{traceId}][%X{spanId}] %t %C{36} %L %M %m%n</Pattern>
// 输出示例:
[2025-05-23 20:14:38]|INFO |[e6bf514d3401c8d3][182eec2e0d9c59a98b9e91575f71d07d].........

2.3. 底层原理

Spring Cloud Sleuth其底层原理基于 Brave(开源链路追踪库)和 分布式上下文传播机制,通过拦截应用间的通信链路(如 HTTP、消息队列等)自动生成和管理追踪数据(Trace/Span

3. 其他

3.1. MDC

MDC(Mapped Diagnostic Context)是一种基于ThreadLocal,用于在日志记录过程中传递上下文信息的机制。它允许将自定义的键值对与日志记录相关联,并在日志输出时自动将这些键值对添加到日志消息中。

3.1.1. 日志框架集成

// ch.qos.logback.classic.util.LogbackMDCAdapter 类
public class LogbackMDCAdapter implements MDCAdapter {
    // 每个线程维护一个 Map,存储 MDC 键值对
    private final ThreadLocal<Map<String, String>> copyOnThreadLocal = new ThreadLocal<>();
    
    @Override
    public void put(String key, String val) {
        Map<String, String> map = copyOnThreadLocal.get();
        if (map == null) {
            map = new HashMap<>();
            copyOnThreadLocal.set(map);
        }
        map.put(key, val);
    }
    
    @Override
    public String get(String key) {
        Map<String, String> map = copyOnThreadLocal.get();
        if (map != null && key != null) {
            return map.get(key);
        } else {
            return null;
        }
    }
    
    // 其他方法...
}
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
    <pattern>%d [%X{traceId},%X{spanId}] %-5level %logger{36} - %msg%n</pattern>
  </encoder>
</appender>

%X{traceId}:表示从 MDC 中获取 traceId 的值。

%X{spanId}:表示从 MDC 中获取 spanId 的值。

3.1.2. 多线程问题和解决方案

问题

在异步或多线程场景下,子线程默认无法获取父线程的 MDC 上下文。

解决方案:

手动传递:在创建子线程时,手动将 MDC 上下文复制到子线程。

使用 阿里巴巴TransmittableThreadLocal对线程池进行包装,自动复制 MDC 上下文。

集成spring cloud Sleuth:自动实现多线程传递MDC上下文

3.2. Brave

Brave 是由 OpenZipkin 社区开发的 分布式链路追踪库,为微服务架构提供基础的追踪能力。Spring Cloud Sleuth 底层基于 Brave 实现。

3.2.1. 设计理念

  • 轻量级与模块化

提供底层 API,不依赖特定框架或平台,可嵌入任何 Java 应用。

  • 模块化设计:

核心模块:提供 Trace/Span 管理、传播协议等基础功能。

集成模块:支持 HTTP、gRPC、Kafka、JDBC 等多种通信协议。

存储模块:适配 Zipkin、Jaeger、Elasticsearch 等后端存储。

  • 无侵入式设计

通过 拦截器(Interceptor)装饰器(Decorator) 模式集成到现有系统,无需修改核心业务逻辑。

例如:通过 ClientRequestInterceptor 拦截 HTTP 请求,自动注入追踪信息。

3.2.2. 常用协议处理

3.2.2.1. Http协议-客户端

功能:在 HTTP 请求发送前注入追踪头(如 B3 头),并记录请求耗时。

核心类:

TracingClientHttpRequestInterceptor :客户端拦截器接口。

HttpClientHandler:处理客户端请求和响应。

示例:详见代码演示

3.2.2.2. Http协议-服务端

功能:从 HTTP 请求头提取追踪信息,创建服务端 Span。

核心类:

TracingFilter:web过滤器拦截请求

HttpServerHandler:处理服务端请求和响应。

HttpServerParser:自定义解析请求和响应的接口。

示例:详见代码演示

3.2.2.3. Feign集成

功能:通过装饰器模式,封装 Feign 客户端,自动处理追踪信息。

核心类:

LazyTracingFeignClient:懒加载封装Feign客户端

TracingFeignClient:追踪信息处理客户端

示例:详见代码演示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值