Java 8 / Camel 2.19.x / AMQ 5.15.x在这里。
我有一个Java应用程序,该应用程序使用Camel从AMQ队列中消费消息,处理这些消息并对其进行处理。有时,路由的输出会将处理结果备份到另一个队列中,以进行进一步的下游处理,但并非总是如此/不必要。典型的Java / Camel / AMQ设置。
我的每条路线(我正在使用Camel XML DSL)都有一个已配置的<onException>
处理程序,通常如下所示:
<onException useOriginalMessage="true">
<exception>java.lang.Exception</exception>
<redeliveryPolicy logStackTrace="true"/>
<handled>
<constant>true</constant>
</handled>
<log message="${exception.stacktrace}" loggingLevel="ERROR"/>
<rollback markRollbackOnly="true"/>
</onException>
非常简单:记录异常并回滚。
作为此<onException>
处理程序的一部分,我想做的是放置原始消息(该消息失败并导致引发异常,不是< / strong>例外!)在特定于路由的 DLQ 中(用“ DLQ”表示,这只是一个队列,可以在其中发送失败的消息以进行审核/报告/播放)
意思是,如果我的应用程序有30条路由,每条路由都从30个不同的AMQ队列中使用,那么我将有30个不同的“ DLQ”,它们各自的<onException>
处理程序会将失败的消息发送到其中。
理想情况下,我希望此配置位于AMQ端(同样也可以位于activem.xml
或类似名称之内),这样,如果需要更改DLQ目的地,则无需更改代码或重新部署。但是,如果只能从Camel路由/配置内部进行操作,那也可以。
我假设,我可以修改每条路由,以包含其自己的针对原始消息的自定义目标DLQ:
<onException useOriginalMessage="true">
<exception>java.lang.Exception</exception>
<redeliveryPolicy logStackTrace="true"/>
<handled>
<constant>true</constant>
</handled>
<log message="${exception.stacktrace}" loggingLevel="ERROR"/>
<rollback markRollbackOnly="true"/>
<to uri="activemq:fizzbuzz.dlq"/>
</onException>
但是我希望有比这更优雅的东西...
有什么想法我该怎么做?
答案 0 :(得分:1)
也许这样对您会更好:
DeadLetterChannelBuilder errorHandlerBuilder = deadLetterChannel("jms:dummy");
errorHandlerBuilder.onPrepareFailure(exchange -> {
exchange.getIn().setHeader("CamelJmsDestinationName",exchange.getIn().getHeader("JMSDestination",String.class).concat(".DLQ"));
});
from("jms:input1")
.to("seda:process");
from("jms:input2")
.to("seda:process");
from("jms:input3")
.to("seda:process");
from("seda:process").errorHandler(errorHandlerBuilder)
.process(exchange -> {
throw new RuntimeException();
});
您可以在运行时计算DLQ队列名称。也可以像配置onException一样配置DeadLetterChannelBuilder。
答案 1 :(得分:0)
如果要在ActiveMQ本身中进行配置,也可以添加特定的policyEntry
并在deadLetterStrategy
中使用通配符,如下例所示:
为所有 INBOUND 队列创建专用的DLQ:
<policyEntry queue="*.INBOUND.>">
<deadLetterStrategy>
<individualDeadLetterStrategy processExpired="false" queuePrefix="" queueSuffix=".DLQ" useQueueForQueueMessages="true"/>
</deadLetterStrategy>
</policyEntry>
在这种情况下,我在所有入站队列中都捕获了使用者的错误:
XXX.INBOUND.AAA -> XXX.INBOUND.AAA.DLQ
YYY.INBOUND -> YYY.INBOUND.DLQ
ZZZ.INBOUND.BBB.CCC -> ZZZ.INBOUND.BBB.CCC.DLQ
但是
NNN.MMM.INBOUND -> ActiveMQ.DLQ
因为模式*
与.
中的点NNN.MMM
字符不匹配。
您可以根据使用情况调整模式。
这对于管理未正确捕获异常的使用者非常有用,并且在ActiveMQ级别完成。