Spring cloud Sleuth链路追踪对于异步线程池的支持

本文探讨了在Spring Cloud应用中使用Sleuth进行日志追踪时,不同线程池配置方式对traceId生成逻辑的影响。重点分析了使用@Async注解时,因AsyncConfigurer配置不当导致traceId无法在主线程与异步线程间共享的问题,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在spring中使用不同的创建线程池的方式调用对日志中traceId的生成逻辑的影响

  • 使用问题:
    用sleuth做日志追踪时,在用到@Async注解做异步时,发现traceId重新生成了,导致 无法和main线程关联到一起。
    追踪源码后发现是因为sleuth对实现了AsyncConfigurer接口的线程池做包装时,由于加载顺序的问题导致未对线程池做代理,导致异步的线程重新生成了traceId。

场景描述:

一.不使用scheduling中的AsyncConfigurer创建线程池
1.使用JDK的ThreadPoolExecutor创建线程池(对应代理类LazyTraceExecutor)
ThreadPoolExecutor jdkExecutor = new ThreadPoolExecutor(5, 20, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(60));
        jdkExecutor.setThreadFactory(new CustomizableThreadFactory("jdkCustomExecutor-"));
        jdkExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  • 其中JDK的executor 对应代理类LazyTraceExecutor,该类只实现了executor的execute方法(对应runnable的代理类SpanContinuingTraceRunnable),
    所以其它调用方式(如submit)都会重新生成traceId。
  • 使用executor.execute()调用的话 main线程和异步线程使用同一个traceId,不同的spanId。其他调用方式都会重新生成traceId。
    因为sleuth-core源码中 org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration 中方法executorBeanPostProcessor
    会对线程池进行代理ExecutorBeanPostProcessor#postProcessAfterInitialization,以支持traceId在异步线程中的输出。
    在这里插入图片描述
    图一

在这里插入图片描述

图二

2.使用spring的ThreadPoolTaskExecutor创建线程池(对应代理类LazyTraceThreadPoolTaskExecutor)
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

b0b0大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值