Apache camel 如何将JMS重新交付到我的驼峰路由中,但仍然允许删除消息

Apache camel 如何将JMS重新交付到我的驼峰路由中,但仍然允许删除消息,apache-camel,jms,activemq,Apache Camel,Jms,Activemq,我有一个骆驼路由,它从ActiveMQ JMS队列读取数据,进行一些处理,并将结果传递到远程目标。如果这个过程的通信部分失败,我想无限期地重试(直到目标“启动”)。我可以通过使路线交易并设置重新交付政策来处理此问题。在Camel(通过Camel.processor.RedeliveryPolicy重新尝试路由的失败部分)和ActiveMQConnectionFactory(通过org.apache.activemq.RedeliveryPolicy重新尝试整个路由)中设置重新交付 我还要求我们能

我有一个骆驼路由,它从ActiveMQ JMS队列读取数据,进行一些处理,并将结果传递到远程目标。如果这个过程的通信部分失败,我想无限期地重试(直到目标“启动”)。我可以通过使路线
交易
并设置
重新交付政策
来处理此问题。在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延迟)。