使用特定于路由的DLQ配置Java / Camel / AMQ

时间:2018-09-26 19:42:41

标签: java apache-camel activemq dead-letter

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>

但是我希望有比这更优雅的东西...

有什么想法我该怎么做?

2 个答案:

答案 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级别完成。