代码之家  ›  专栏  ›  技术社区  ›  hotmeatballsoup

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

  •  0
  • hotmeatballsoup  · 技术社区  · 6 年前

    java8/Camel 2.19.x/amq5.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>
    

    非常简单:记录异常并回滚。

    我想做的是,作为这件事的一部分 < 处理程序,放置 原始消息 (失败并导致抛出异常, 例外!)在特定路线上 DLQ公司

    也就是说,如果我的应用程序有30个路由,每个路由都来自30个不同的AMQ队列,那么我就有30个不同的“dlq”,其中每个路由各自 < 处理程序会将失败的消息发送到。

    理想的情况下,我希望这个配置是在AMQ方面(再次也许在 activem.xml 或者类似的)这样,如果DLQ目的地需要更改,我就不需要进行代码更改或重新部署。但如果只能从Camel route/configs内部执行,那也没关系。

    假设 我可以修改每个路由以包含其自己的自定义目标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>
    

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   c0ld    6 年前

    也许这样对你更好:

                 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队列名称。DeadLetterChannelBuilder也可以像OneException一样配置。

        2
  •  0
  •   рüффп Ruwantha    4 年前

    如果要在ActiveMQ本身中进行配置,还可以添加特定的 policyEntry 并在 deadLetterStrategy 比如这个例子:

    为所有人创建专用的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级别完成的。