Spring Cloud Sleuth已死

903 阅读2分钟

Spring Cloud Sleuth

Spring Cloud Sleuth 是Spring Cloud的分布式链路跟踪解决方案组件,通过拦截请求并在日志中添加Span和Trace的信息,可以帮助我们快速定位问题。然而,Sleuth本身并不提供链路跟踪数据的展示和分析功能,因此通常需要与APM系统(如Zipkin、Skywalking和Pinpoint)进行集成。

新宠 Micrometer Tracing

今天创建新项目跟进SpringBoot 3.x版本,发现spring-cloud-dependencies的pom.xml已经把spring-cloud-sleuth的相关依赖移除,导致无法下载依赖包

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

Spring Cloud 2022.0 发布说明

  • Spring Cloud Sleuth
    • This project has been removed from the release train. The core of this project has moved to Micrometer Tracing project and the instrumentations will be moved to Micrometer and all respective projects (no longer all instrumentations will be done in a single repository.

好吧,又得学习新技术,反正都用最新的SpringBoot 3.x版本啦,也不差这个Micrometer Tracing

简单使用

公司项目使用spring-cloud-starter-sleuth 主要用于日志打印traceId 然后通过阿里云日志服务SLS进行采集、搜索和分析。那现在就改为micrometer-tracing 能实现原有功能就行。

<!--        <dependency>-->  
<!--            <groupId>org.springframework.cloud</groupId>-->  
<!--            <artifactId>spring-cloud-starter-sleuth</artifactId>-->  
<!--        </dependency>-->
<dependency>  
    <groupId>io.micrometer</groupId>  
    <artifactId>micrometer-tracing-bridge-brave</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-actuator</artifactId>  
</dependency>

替换依赖包就解决啦,是不是很简单😁,官方文档在这 Micrometer官方例子 有空再去详细学习。

异步子线程和RPC框架的链路跟踪是通过从org.slf4j.MDC中复制参数进行传递实现的,micrometer-tracingspring-cloud-starter-sleuth一样会设置traceIdspanIdMDC 中,所以完美兼容。

遇到的问题

之前的spring-cloud-starter-sleuth@Scheduled 定时任务也是会生成链路跟踪数据的,替换micrometer-tracing之后就不生效了,Spring官方回复在 issues 结论是SpringFramework的6.1.0版本修复了,而当前最新的SpringBoot版本是3.1.2,使用的是SpringFramework的6.0.11版本,这这这......

还好StackOverflow 已经有人遇到一样的问题,直接抄答案:

import io.micrometer.tracing.Span;  
import io.micrometer.tracing.Tracer;  
import lombok.RequiredArgsConstructor;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Pointcut;  
import org.springframework.stereotype.Component;

@Aspect  
@Component  
@RequiredArgsConstructor  
public class ScheduledSpanAspect {  
    private final Tracer tracer;  
  
    @Pointcut("@annotation(org.springframework.scheduling.annotation.Scheduled)")  
    public void annotatedWithScheduled() {  
    }  
  
    @Around("annotatedWithScheduled()")  
    public Object wrapScheduledIntoSpan(ProceedingJoinPoint pjp) throws Throwable {  
        String methodName = pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName();  
  
        Span span = tracer.nextSpan()  
                .name(methodName)  
                .start();  
        try (Tracer.SpanInScope ignoredSpanInScope = tracer.withSpan(span.start())) {  
            return pjp.proceed();  
        } finally {  
            span.end();  
        }  
    }  
}