SpringBoot链路追踪traceId丢失解决方案
·
SpringBoot中使用链路追踪时,由于多线程之间的切换、或者使用的不是Spring提供的线程池时会发生traceId丢失。
处理方式一
线程池使用的是Spring提供的:ThreadPoolTaskExecutor,可以通过实现TaskDecorator解决
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(4);
taskExecutor.setMaxPoolSize(8);
taskExecutor.setQueueCapacity(100);
taskExecutor.setThreadNamePrefix("taskExecutor-");
taskExecutor.setKeepAliveSeconds(30);
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setTaskDecorator(runnable -> () -> {
try {
// 获取当前线程的 MDC 上下文
Map<String, String> contextMap = MDC.getCopyOfContextMap();
// 将 MDC 上下文传递到新线程
if (Objects.nonNull(contextMap)) {
MDC.setContextMap(contextMap);
}
// 执行任务
runnable.run();
} finally {
// 清理 MDC 上下文,避免内存泄漏
MDC.clear();
}
});
taskExecutor.initialize();
return taskExecutor;
}
处理方式二
直接手动创建一个链路,然后把traceId放入log的MDC上下文中
// 注入trace依赖
@Resource
private Tracer tracer;
// 示例片段
Span span = tracer.spanBuilder().start();
try {
TraceContext context = span.context();
MDC.put("traceId", context.traceId());
MDC.put("spanId", context.spanId());
} finally {
span.end();
MDC.remove("traceId");
MDC.remove("spanId");
}
处理方式三
如果是有上级链路,需要当前线程继续传递下去,可以使用CurrentTraceContext的wrap方法
// 注入依赖
@Resource
private Tracer tracer;
// 代码片段
CurrentTraceContext traceContext = tracer.currentTraceContext();
// 根据需要使用对于的包装方法
<C> Callable<C> wrap(Callable<C> var1);
Runnable wrap(Runnable var1);
Executor wrap(Executor var1);
ExecutorService wrap(ExecutorService var1);
更多推荐


所有评论(0)