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

Spring Boot 3+中@Async方法导致Micrometer追踪日志丢失的问题求助

问题根源

使用@Async后,异步线程会脱离原请求的上下文,导致Micrometer TraceContext(包含traceId、spanId)没有被传递到新线程,所以日志和Kafka的观测数据都丢失了追踪信息。

解决方案

1. 配置支持TraceContext传递的异步任务执行器

自定义异步配置类,用Micrometer的TraceableExecutorService包装任务执行器,确保异步线程继承父线程的TraceContext:

import io.micrometer.tracing.Tracer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableAsync
public class AsyncTraceConfig implements AsyncConfigurer {

    private final Tracer tracer;

    public AsyncTraceConfig(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("Async-Trace-");
        // 包装执行器,传递TraceContext
        executor.initialize();
        return new TraceableExecutorService(executor.getThreadPoolExecutor(), tracer);
    }
}

2. 确保日志MDC上下文传递

如果你的日志是通过MDC输出traceId/spanId,需要让异步线程复制父线程的MDC内容,避免日志中仅显示空的追踪标识。自定义一个TaskDecorator实现:

import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;

import java.util.Map;

public class MdcTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        // 捕获当前线程的MDC上下文
        Map<String, String> mdcContext = MDC.getCopyOfContextMap();
        return () -> {
            try {
                // 恢复MDC上下文到异步线程
                if (mdcContext != null) {
                    MDC.setContextMap(mdcContext);
                }
                runnable.run();
            } finally {
                // 清理MDC,避免线程复用导致上下文污染
                MDC.clear();
            }
        };
    }
}

然后在上述的线程池配置中添加这个装饰器:

executor.setTaskDecorator(new MdcTaskDecorator());

3. 验证Kafka观测的上下文关联

你已经开启了kafkaTemplate.setObservationEnabled(true),当TraceContext成功传递到异步线程后,Kafka生产者的观测数据会自动关联到父trace,生成完整的调用链span。

额外检查点
  • 确认Spring Boot版本:如果是2.x版本,需使用Spring Cloud Sleuth而非原生Micrometer Tracing,配置逻辑需调整。
  • 检查日志格式:确保日志pattern包含追踪标识占位符,比如:
    logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:26:26