You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Sleuth工作机制及库调用追踪问题咨询

嘿,我来帮你梳理下Spring Cloud Sleuth的相关问题,刚好之前踩过类似的坑😉

Spring Cloud Sleuth底层工作原理

简单来说,Sleuth的核心是靠ThreadLocal在同一个请求线程里传递追踪标识——也就是traceId(整个链路的唯一ID)和spanId(每个调用节点的ID)。它会通过各种拦截器自动埋点:

  • 当请求进入Spring应用时,Servlet拦截器会创建一个根Span,把traceId和spanId存入ThreadLocal;
  • 如果你用RestTemplate/WebClient调用其他服务,Sleuth的客户端拦截器会把这些标识塞进请求头(比如X-B3-TraceId、X-B3-SpanId)传递给下游;
  • 同时,它会自动把这些ID注入到日志里,让你能轻松串联整个调用链路的日志。
它是否支持追踪库调用?

当然支持,但得看你的调用方式:

  • 如果是同一个线程内的本地库方法调用:Sleuth默认不会自动生成子Span(因为它默认只拦截HTTP、消息队列这类跨边界的调用),但可以手动或通过AOP配置来追踪;
  • 如果是通过HTTP调用外部库服务:只要客户端和服务端都正确集成Sleuth,就能自动追踪整个链路。
解决项目A调用库B Controller无法追踪的问题

你得先明确自己是哪种调用场景,下面分两种常见情况给你解决方案:

场景1:本地调用库B的Controller方法(库B是Jar依赖,和项目A在同一个应用内)

如果项目A是直接注入库B的Controller然后调用其方法(比如@Autowired LibraryBController后直接调用bEndpoint()),这属于本地方法调用,Sleuth不会自动创建子Span。这时候有两种办法:

方法1:手动创建Span追踪单个调用

用Sleuth提供的Tracer类手动生成子Span:

import brave.Tracer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProjectAController {

    @Autowired
    private Tracer tracer;

    @Autowired
    private LibraryBController libraryBController;

    @GetMapping("/a-endpoint")
    public String aEndpoint() {
        // 创建一个名为"call-library-b-controller"的子Span
        try (Tracer.SpanInScope span = tracer.nextSpan().name("call-library-b-controller").start().scope()) {
            return libraryBController.bEndpoint();
        }
    }
}

方法2:用AOP自动追踪所有库B方法调用

如果想让所有对库B Controller的调用都自动生成Span,可以用Spring AOP做一个切面:

import brave.Tracer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LibraryBTracingAspect {

    @Autowired
    private Tracer tracer;

    // 匹配库B Controller下的所有方法,根据你的包路径调整
    @Around("execution(* com.example.libraryb.controller..*(..))")
    public Object traceLibraryBCalls(ProceedingJoinPoint joinPoint) throws Throwable {
        String spanName = "library-b-" + joinPoint.getSignature().getName();
        try (Tracer.SpanInScope span = tracer.nextSpan().name(spanName).start().scope()) {
            return joinPoint.proceed();
        }
    }
}

记得要引入Spring AOP的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

场景2:通过HTTP请求调用库B的Controller(库B是独立服务)

如果是这种情况,需要确保两个关键点:

1. 项目A的HTTP客户端被Sleuth拦截

对于RestTemplate:如果你是用@Bean或RestTemplateBuilder创建的,Sleuth会自动添加追踪拦截器。但如果是手动new RestTemplate(),得手动加拦截器:

import brave.spring.web.TraceClientHttpRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(TraceClientHttpRequestInterceptor traceInterceptor) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getInterceptors().add(traceInterceptor);
        return restTemplate;
    }
}

对于WebClient,Sleuth也会自动配置,只要你用WebClientBuilder创建实例就行。

2. 库B集成Spring Cloud Sleuth

在库B的依赖中添加Sleuth starter:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

同时,确保库B的日志配置里包含traceId和spanId,比如logback.xml的日志格式:

<encoder>
    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %X{traceId:-} %X{spanId:-}%n</pattern>
</encoder>

这样库B就能接收项目A传递的追踪标识,把自己的调用节点加入整个链路了。


内容的提问来源于stack exchange,提问作者Kiki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:33:57