【发布时间】:2015-12-13 05:01:24
【问题描述】:
我在将 Apache Camel 与 Oracle 高级队列和 JMS 结合使用时遇到了问题。
这是关于分发消息的应用程序。在 Camel 的帮助下,消息在 Oracle 高级队列中被接收和排队。然后它们被 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 以使用队列中的第一条消息? 没找到直接在camel上配置的选项……
【问题讨论】:
-
在 JMS 中,一般不保证消息的顺序。在 ActiveMQ 中,如果你只有一个消费者,并且客户端重新交付,你是相当安全的,但我不知道 Oracle AQ...
-
如果没有针对此问题的通用解决方案,我会对 Weblogic 应用程序服务器的解决方案感兴趣。
-
解决这个问题的(干净)解决方案始终是服务器端,因为客户端(应该/)不知道队列中的消息。根据您的 QoS,您需要读取队列中的所有消息以确定您首先想要的消息 - 根据您的选项(配置明智),哪个仍然可能是一个选项。在您在客户端实施此操作之前,我会在下面检查我的答案/服务器端的配置。 HTH
-
事后看来,问题似乎是在高级队列数据库端设置的延迟。这导致 Camel 框架在发生错误的情况下完全回滚之前的事务之前使用下一条消息。很高兴知道在这种情况下这是否是正确的事情或 Oracle AQ 实施的疏忽。
-
@PhilW:这是否意味着我必须在 Camel 和数据库之间放置一个像 Apache ActiveMQ 这样的消息代理?据我了解,这些消息代理的用途与 Oracle 高级队列相同。这不过是另一个队列。那是对的吗?那么没有一个已经过时了吗?
标签: java jms apache-camel advanced-queuing