Camel 和 JMS 以正确的顺序从高级队列中消费消息

Consuming message in the correct order from an Advanced Queue by Camel and JMS

我在将 Apache Camel 与 Oracle Advanced Queues 和 JMS 结合使用时遇到问题。

这是关于分发消息的应用程序。在 Camel 的帮助下,消息在 Oracle Advanced Queues 中接收和排队。然后它们被 Camel 消耗并转发到目标系统。 对于消息发送失败的情况,在Advanced Queue中定义了一个重试次数,使消息重复发送。

如果 Camel 现在使消息出列并将其发送到不可用的目标系统,则会抛出 HttpOperationFailedException 或 NoSuchEndpointException。这些被捕获并执行回滚。

此时,期望按照重试计数中定义的频率重试消息传递,然后将其移至异常队列。 但是,正在发生的是队列中的下一条消息已发送。

由于消息的内容部分相互依赖,所以必须按顺序处理。

我认为 JMS 库的使用存在错误配置,但我不确定并且没有发现任何可以影响此行为的东西。

使用的 JMS 库是 Oracle AqApi v 11.2.0.3。

这是骆驼路线的代码:

from("jms-camel-component:myComponent.AQ?jmsMessageType=Text").routeId("deliveryToTarget")
        .transacted()                
        .setExchangePattern(ExchangePattern.InOut)                        
        .setHeader(Exchange.HTTP_QUERY, constant("throwExceptionOnFailure=false"))
        .setHeader(Exchange.CONTENT_TYPE, constant("application/xml; charset=UTF-8"))
        .doTry()
            .recipientList(header("endpointTarget"))
            .endDoTry()
            .process(ResponseProzessor.getInstance())
            .log("Message was delivererd.")
        .doCatch(HttpOperationFailedException.class, NoSuchEndpointException.class)    
            .process(ResponseProzessor.getInstance())
            .log("Error occured.")
            .rollback()
        .end();

这里是 JmsComponent 配置:

JmsComponent jmsComponent = new JmsComponent(scc);
jmsComponent.setConnectionFactory(connectionFactory);
jmsComponent.setTransactionManager(tm);
jmsComponent.setMaxConcurrentConsumers(1);            
jmsComponent.setMaxMessagesPerTask(1);                  
jmsComponent.setIncludeSentJMSMessageID(true);

提前感谢您的帮助!

更新

我想,我已经找到了所描述行为的原因。在高级队列上配置了延迟。只要延迟持续,队列中的下一条消息就会出队。消息不是随机出列的,它们是根据优先级出列的。

我真的认为这是必须在消费者身上配置的东西。是否有任何技巧可以将 camel-jms-component 配置为使用来自队列的第一条消息,只要它没有提交或移动到异常队列? 我没有找到直接在骆驼上配置它的选项...

我不是 Oracle AQ 专家,但据我所知,这是队列上的设置,而不是客户端上的设置。

The sort_list parameter determines the order in which messages are dequeued. You cannot change the message sort order after you have created the queue table

来自: http://docs.oracle.com/cd/B19306_01/server.102/b14257/aq_admin.htm

您很可能设置了 ENQ_TIME 或 COMMIT_TIME - 这可能已经满足您的需求。

当然,您的消费者必须是唯一的。