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

配置启用MDC日志的Apache Camel路由时MDC值丢失问题

Apache Camel路由中MDC日志丢失问题解决

问题原因

你的路由中使用了multicast().parallelProcessing(),该配置会开启新线程并行处理消息。由于MDC(Mapped Diagnostic Context)基于**线程本地存储(ThreadLocal)**实现,线程切换后原线程的MDC上下文无法自动传递到新线程,导致日志中无法获取到MDC值。

解决方案

1. 禁用并行处理(业务允许情况下)

如果业务逻辑不需要并行执行,直接移除.parallelProcessing()配置,让multicast在原线程执行,MDC上下文会自然保留:

.when(header("type").isEqualTo("DealInvitationEvent"))
    .multicast()
    // 去掉.parallelProcessing()
    .process(invitationEventProcessor)
.end()

2. 配置MDC感知的线程池

利用Camel提供的MDCThreadPoolFactory,让并行线程继承原线程的MDC上下文:

步骤1:定义MDC感知的线程池Bean

import org.apache.camel.util.concurrent.MDCThreadPoolFactory;
import org.apache.camel.util.concurrent.DefaultThreadFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Bean
public ExecutorService multicastMdcExecutor() {
    return new ThreadPoolExecutor(
        5, // 核心线程数
        10, // 最大线程数
        60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(),
        new MDCThreadPoolFactory(new DefaultThreadFactory("multicast-mdc-pool"))
    );
}

步骤2:路由中指定该线程池

.when(header("type").isEqualTo("DealInvitationEvent"))
    .multicast(multicastMdcExecutor()) // 传入自定义线程池
    .parallelProcessing()
    .process(invitationEventProcessor)
.end()

3. 手动传递MDC上下文(无侵入线程池配置)

如果不想修改线程池,可以通过Exchange属性手动传递MDC:

步骤1:在前置Processor中保存MDC到Exchange

在outboxHeaderEnricherProcessor中添加代码,将当前MDC上下文存入Exchange属性:

import org.slf4j.MDC;
import java.util.Map;

public void process(Exchange exchange) throws Exception {
    // 保存当前MDC上下文到Exchange属性
    Map<String, String> mdcContext = MDC.getCopyOfContextMap();
    exchange.setProperty("MDC_CONTEXT", mdcContext);
    
    // 原有业务逻辑...
}

步骤2:在并行Processor中恢复MDC

在每个并行处理的Processor(如invitationEventProcessor、enquiryAcceptedEventProcessor等)开头添加恢复逻辑:

import org.slf4j.MDC;
import java.util.Map;

public void process(Exchange exchange) throws Exception {
    // 从Exchange属性中取出MDC上下文并恢复
    Map<String, String> mdcContext = exchange.getProperty("MDC_CONTEXT", Map.class);
    if (mdcContext != null) {
        MDC.setContextMap(mdcContext);
    }
    
    // 原有业务逻辑...
    
    // 可选:处理完成后清除当前线程MDC,避免线程复用导致上下文污染
    // MDC.clear();
}

额外检查点

  • 确认application.yml中的MDC配置已生效:启动日志中搜索MDCLogging,应能看到“Enabled MDC logging”相关输出。
  • 调用producerTemplate前,确保MDC值已正确设置(比如在调用方代码中MDC.put("key", "value"))。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:50:42