在我的JMS应用程序上,我们在Producer上使用临时队列,以便能够从Consumer应用程序接收回复。
每当我在网络中重新启动任意代理时,在尝试将回复发送到临时队列时,我的消费者应用程序日志中出现了很多这样的错误:
javax.jms.InvalidDestinationException:
Cannot publish to a deleted Destination: temp-queue://ID:...
然后我看到加里在那里建议使用
的回应jms.watchTopicAdvisories=false
作为客户端brokerURL
上的网址参数。我使用此附加参数立即更改了客户端代理URL。但是现在,当我在网络中重启我的代理以进行此故障转移测试时,我发现这样的错误:
javax.jms.JMSException:
The destination temp-queue:
//ID:client.host-65070-1308610734958-2:1:1 does not exist.
我正在使用ActiveMQ 5.5版本。我的客户经纪人URL如下所示:
failover:(tcp://amq-host1:61616,tcp://amq-host2.tred.aol.com:61616,tcp://amq-host3:61616,tcp://amq-host4:61616)?jms.useAsyncSend=true&timeout=5000&jms.watchTopicAdvisories=false
此外,这是我的4个代理之一的activemq配置XML: amq1.xml
有人可以在这里查看这个问题并建议我在这个设置中犯了什么错误。
进一步澄清我在代码中如何进行请求 - 响应:
答案 0 :(得分:25)
有一个代理属性org.apache.activemq.broker.BrokerService #cacheTempDestinations应该有助于故障转移:case。 在xml配置中将其设置为true,并且在客户端断开连接时不会立即删除临时目标。 快速故障转移:重新连接将能够再次从临时队列生成和/或使用。
有一个基于timeBeforePurgeTempDestinations(默认为5秒)的计时器任务,用于处理缓存删除。
但有一点需要注意,我没有在activemq-core中看到任何使用该属性的测试,因此我无法对此提供任何保证。
答案 1 :(得分:9)
在请求 - 回复方案中请求者(生产者)所连接的代理上创建临时队列。它们是从javax.jms.Session
创建的,因此在该会话断开连接时,由于客户端断开连接或代理失败/故障转移,这些队列将永久消失。当你的一个消费者试图回复这些队列时,其他经纪人都不会理解其含义;因此你的例外。
这需要思维方式的架构转变,假设您要处理故障转移并保留所有消息。以下是您可以解决问题的一般方法:
queue:response.<client id>
。如果您的客户端数量有限,则客户端ID可能是标准名称;如果您拥有大量客户端,则客户端ID可能是UUID。JMSCorrelationID
标头中设置的,应该从请求复制到响应消息。这与Apache Camel request-response over messaging采用的方法类似。
有一点需要注意的是,当客户端执行时,队列不会消失,因此您应该设置一个生存在响应消息上的时间,以便在未被消耗时从代理中删除它,否则你会收到积压的未消息消息。您还需要设置dead letter queue strategy to automatically discard expired messages。