Camel ProducerTemplate发送ActiveMQ消息处理结果与路由发送不一致问题
根因分析
- 交换模式不匹配:
ProducerTemplate.requestXXX、FluentProducerTemplate.request默认使用*InOut(请求应答)交换模式,而StartRoute中直接.to("activemq:save")默认使用InOnly(仅发送)*交换模式,两者附带的JMS消息头、后续路由处理逻辑存在本质差异。 - 资源滥用问题:在
process方法中每次调用都新建ProducerTemplate和FluentProducerTemplate,未主动关闭会导致每次生成新的ActiveMQ客户端连接和随机clientID,大量残留无效资源。 - 逻辑适配缺失:
SaveRoute没有针对InOut模式做应答返回逻辑,request方法会导致请求超时、JMS相关头残留,残留的clientID、JMSCorrelationID等头信息会被文件组件默认当作文件名使用,就是你观察到的随机文件名问题。 - 日志缺失原因:InOut模式下消息会被标记为需要返回应答,默认不会触发消费路由的普通日志规则,或者新建的ProducerTemplate未继承原有路由的日志上下文,都会导致控制台无对应日志输出。
修复方案
- 统一交换模式,无应答需求时使用发送模式而非请求模式:
// 替换requestBodyAndHeaders为sendBodyAndHeaders,使用InOnly模式匹配路由默认行为 template.sendBodyAndHeaders("activemq:save", "Batch Job Started", map); // FluentProducerTemplate替换request为send FluentTemplate .withHeader(".....", ".....") .withHeader(".....", ".....") .to("activemq:save") .send();
- 复用ProducerTemplate实例,避免重复创建资源:
不要在process方法中每次新建模板,最优方案是将ProducerTemplate、FluentProducerTemplate注册为全局单例复用;如果必须在process内创建,要在使用完成后主动关闭:
try { ProducerTemplate template = exchange.getContext().createProducerTemplate(); // 调用逻辑 } finally { template.stop(); FluentTemplate.stop(); }
- 显式配置文件生成规则,避免JMS头干扰:
在SaveRoute中清理无用的JMS头,显式指定文件名规则:
from("activemq:save") .log("started saving") .process(new FormatText()) .removeHeaders("JMS*") // 清理所有JMS相关头信息 .setHeader("CamelFileName", constant("status.log")) // 按需自定义文件名规则 .to("file:///status");
- 强制指定端点交换模式,从根源避免模式不一致:
可以在ActiveMQ端点配置中强制指定交换模式,无需再关注发送侧的模式配置:
// 消费侧强制统一为InOnly模式 from("activemq:save?exchangePattern=InOnly") .log("started saving") .process(new FormatText()) .to("file:///status");
内容的提问来源于stack exchange,提问作者Szilágyi István
相关产品推荐
相关产品推荐

