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

Apache Camel调用pollEnrich后如何打印correlationId(exchangeId)

问题描述

Apache Camel路由处理邮件内容场景下,已通过getContext().setUseMDCLogging(true);开启MDC日志功能,在logback.xml中通过%X{camel.exchangeId}配置打印关联ID(即exchangeId)。但调用pollEnrich()方法后,原exchangeId 95C1D8CE0CF95D7-0000000000000001 无法在后续日志中输出,对应日志位置的%X{camel.exchangeId}取值为空。

现有配置

路由代码

@Override
public void configure() throws Exception {
    
    getContext().setUseMDCLogging(true);
    
    from("direct:process_polling_email")
    .log("Hello World")
    .routeId("routeId_123456789")
    .doTry()
        .log("doTry: exchangeProperty.subject - ${exchangeProperty.subject}")
        .pollEnrich().simple("...."
                + "?username={{imap.username}}&"
                + "password={{imap.password}}&"
                +"folderName={{imap.fetch.folder}}&"
                +"copyTo={{imap.tocopy.folder}}&"
                +"searchTerm.subject=${exchangeProperty.subject}&"
                +"fetchSize=1&"
                +"searchTerm.unseen=true&"
                + "closeFolder=false&"
                + "disconnect=false&"
                +"sendEmptyMessageWhenIdle=true&"
                +"bridgeErrorHandler=true")
    .endDoTry()
    .log("After pollEnrich ");
}

logback.xml配置

<encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} %X{camel.exchangeId} - %msg%n</pattern>
</encoder>

实际日志输出

2022-06-03 13:39:00 [Camel (camel-1) thread #6 -  INFO  routeId_123456789 95C1D8CE0CF95D7-0000000000000001 - doTry: exchangeProperty.subject - Hello World
2022-06-03 13:39:01 [Camel (camel-1) thread #6 -  INFO  routeId_123456789  - After pollEnrich
问题原因

pollEnrich是Camel的内容增强EIP,默认行为是用拉取到的新Exchange直接替换原路由中的Exchange实例。Camel的MDC日志上下文是和当前Exchange绑定的,默认聚合策略不会自动把原Exchange的MDC属性、exchangeId传递给新Exchange,同时部分旧版本Camel存在pollEnrich执行后MDC上下文未正确回填的已知问题,最终导致后续日志无法获取到camel.exchangeId的值。

解决方案

可根据实际场景选择以下任意一种方案修复:

  • 方案1:显式指定聚合策略,手动传递上下文
    给pollEnrich添加自定义聚合策略,在合并新旧Exchange时手动保留原exchangeId并回填MDC,适配所有Camel版本,示例代码:
    .pollEnrich()
    .simple("你的IMAP端点完整URI")
    .aggregateStrategy((oldExchange, newExchange) -> {
        // 适配sendEmptyMessageWhenIdle=true返回空的场景
        if (newExchange == null) {
            return oldExchange;
        }
        // 保留原Exchange的ID
        String originalExchangeId = oldExchange.getExchangeId();
        // 复制原Exchange的全部属性到新Exchange
        newExchange.getProperties().putAll(oldExchange.getProperties());
        // 手动回填MDC中的exchangeId
        MDC.put("camel.exchangeId", originalExchangeId);
        return newExchange;
    })
    
  • 方案2:升级Camel版本
    Camel 3.14及以上LTS版本已修复pollEnrich类EIP执行后MDC上下文丢失的问题,升级后无需额外编码即可自动传递camel.exchangeId到后续日志。
  • 方案3:pollEnrich执行后手动恢复MDC值
    如果不需要修改聚合逻辑,可以在pollEnrich前后加简单处理,手动把exchangeId写回MDC:
    // 先把原exchangeId存为Exchange属性
    .setProperty("originalExchangeId", exchangeProperty("CamelExchangeId"))
    .pollEnrich().simple("你的IMAP端点完整URI")
    // 执行后手动回填MDC
    .process(exchange -> {
        String originalId = exchange.getProperty("originalExchangeId", String.class);
        MDC.put("camel.exchangeId", originalId);
    })
    
  • 方案4:配置MDC键传递规则
    除了开启MDC日志外,额外配置MDC键的传递匹配规则,让Camel自动传递所有camel开头的上下文属性:
    getContext().setUseMDCLogging(true);
    // 新增配置,匹配所有camel开头的MDC键做跨节点传递
    getContext().setMDCLoggingKeysPattern("camel.*");
    
    该方案在Camel 3.x以上部分版本可直接解决问题,不需要修改路由逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:24:23