Apache camel 如何将JMS重新交付到我的驼峰路由中,但仍然允许删除消息
我有一个骆驼路由,它从ActiveMQ JMS队列读取数据,进行一些处理,并将结果传递到远程目标。如果这个过程的通信部分失败,我想无限期地重试(直到目标“启动”)。我可以通过使路线Apache camel 如何将JMS重新交付到我的驼峰路由中,但仍然允许删除消息,apache-camel,jms,activemq,Apache Camel,Jms,Activemq,我有一个骆驼路由,它从ActiveMQ JMS队列读取数据,进行一些处理,并将结果传递到远程目标。如果这个过程的通信部分失败,我想无限期地重试(直到目标“启动”)。我可以通过使路线交易并设置重新交付政策来处理此问题。在Camel(通过Camel.processor.RedeliveryPolicy重新尝试路由的失败部分)和ActiveMQConnectionFactory(通过org.apache.activemq.RedeliveryPolicy重新尝试整个路由)中设置重新交付 我还要求我们能
交易
并设置重新交付政策
来处理此问题。在Camel(通过Camel.processor.RedeliveryPolicy
重新尝试路由的失败部分)和ActiveMQConnectionFactory(通过org.apache.activemq.RedeliveryPolicy
重新尝试整个路由)中设置重新交付
我还要求我们能够从JMS队列中删除一个条目(我通过一个通过JMX与ActiveMQ对话的应用程序来删除),并且处理应该转移到下一条消息
问题是,我可以允许删除消息(通过将使用者设置为cacheLevelName=CACHE\u NONE
),也可以重试连接句柄(通过将使用者设置为cacheLevelName=CACHE\u consumer
),但不能同时进行这两种操作
以下是我当前的设置:
使用非常简单的路线:
@组件
公共类TransactiveRoute扩展了SpringRouteBuilder{
@凌驾
public void configure(){
onException(Exception.class)//我们将在这里处理comms异常
.redeliveryPolicyRef(“redeliveryProfile”)
.rollback();
from(“jms:queue:myqueue?cacheLevelName=CACHE\u CONSUMER”)
.已交易(“需要传播”)
.bean(Bean1.class)
.to(DESTINATION);//这可能引发comms异常
}
}
通过此设置,路由从jms:queue:myqueue
读取,并且在出现通信异常的情况下,Camel会在内部重试从到
部分的路由两次(重新交付profile
)。然后,在5秒钟的延迟后,消息再次通过整个路由发送(amqRedeliveryPolicy
)。这会一直持续到我停止测试
但是,如果我从ActiveMQ中删除消息,它将继续由路由处理,尽管它不再在队列中
如果我将消费者更改为:
from("jms:queue:myqueue?cacheLevelName=CACHE_NONE")
我现在可以从ActiveMQ中删除消息,路由将停止处理它。。。但是amqRedeliveryPolicy
被忽略,消息将立即重试(无5秒延迟),并在尝试6次后(AMQ的默认设置)被放入死信队列
那么,有没有办法通过修改我的配置来实现这两个目标呢
还是我完全没有抓住要点?如果您需要人工干预来通过JMX删除队列上的特定消息,这听起来有点像一个糟糕的设计 也许您可以让AMQ在尝试X次失败后将消息移动到DLQ—永久重新交付也是一个糟糕的设计。但如果尝试次数为6次,则可以将默认值增加到更高的值 然后,您可以从DLQ队列中检查消息,并尝试了解消息失败的原因,并且您可以始终通过JMX或其他工具安全地删除或清除DLQ队列
AMQ允许每个队列有一个DLQ,您可以将其配置为使用DLQ前缀等,而不是一个普通的DLQ队列。是的,这是一个奇怪的设计-我们从中读取的队列实际上是用户可见的(通过应用程序的另一部分),并且我们要求用户能够删除消息。
到(…)
部分实际上是一个远程系统,可能会关闭,在这种情况下,我们希望重试,直到目标启动,或者用户删除消息。基本上,如果出现通信错误,我们将回滚事务-我将修改我的问题以使其更清楚。我做了更多的尝试,发现在路由的到(…)
上,将确认模式名设置为客户端确认,意味着我会不断重试,确认消息删除,但消息在骆驼内部重新传递后立即重新传递(无5s延迟)。