首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ActiveMQ:如何在使用临时队列时处理代理故障转移

ActiveMQ:如何在使用临时队列时处理代理故障转移
EN

Stack Overflow用户
提问于 2011-06-22 06:15:33
回答 2查看 20.9K关注 0票数 54

在我的JMS应用程序中,我们在生产者上使用临时队列,以便能够接收来自消费者应用程序的回复。

我正面临着与本帖子中提到的完全相同的问题:http://activemq.2283324.n4.nabble.com/jira-Created-AMQ-3336-Temporary-Destination-errors-on-H-A-failover-in-broker-network-with-Failover-tt-td3551034.html#a3612738

每当我重新启动网络中的任意代理时,在尝试向临时队列发送回复时,我都会在消费者应用程序日志中收到许多类似以下内容的错误:

代码语言:javascript
复制
javax.jms.InvalidDestinationException:
  Cannot publish to a deleted Destination: temp-queue://ID:...

然后我看到了加里的回复,建议使用

代码语言:javascript
复制
jms.watchTopicAdvisories=false

作为客户端brokerURL上的url参数。我立即用这个附加参数更改了我的客户端代理URL。但是,现在当我在网络中重新启动代理以进行此故障转移测试时,我看到了类似这样的错误:

代码语言:javascript
复制
javax.jms.JMSException: 
  The destination temp-queue:
    //ID:client.host-65070-1308610734958-2:1:1 does not exist.

我使用的是ActiveMQ 5.5版本。我的客户端代理URL如下所示:

代码语言:javascript
复制
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 config XML:amq1.xml

这里有人能调查一下这个问题,并建议我在这个设置中犯了什么错误吗?

更新:

为了进一步阐明我是如何在代码中执行请求-响应的:

  1. I已经使用了每个生产者的目的地(即临时队列),并在每个消息的reply-to标头中设置了这个。
  2. 我已经在JMSCorrelationID标头中发送了一个每个消息唯一的相关标识符。据我所知,甚至Camel和
  3. 也在使用临时队列作为请求-响应机制。唯一的区别是Spring JMS实现为每个消息创建和销毁临时队列,而我在生产者的生命周期内创建临时队列。当客户端(生产者)应用程序关闭时,此临时队列将被销毁,或者当AMQ broker意识到没有活动的生产者附加到此临时队列时,它将销毁此临时队列。
  4. 我已经在生产者端的每个消息上设置一个消息过期时间,以便消息不会在队列中停留太长时间(60秒)。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-27 00:02:03

有一个代理属性org.apache.activemq.broker.BrokerService#cacheTempDestinations应该有助于故障转移: case。在xml配置中将其设置为true,则在客户端断开连接时不会立即删除临时目标。快速故障转移:重新连接将能够再次从临时队列中产生和/或消费。

有一个基于timeBeforePurgeTempDestinations的计时器任务(默认为5秒)来处理缓存删除。

但需要注意的是,我在activemq-core中没有看到任何使用该属性的测试,所以我不能在这一点上给你任何保证。

票数 27
EN

Stack Overflow用户

发布于 2012-01-25 21:38:53

临时队列是在请求-应答场景中请求者(生产者)所连接的代理上创建的。它们是从javax.jms.Session创建的,因此在该会话断开连接时,无论是由于客户端断开连接还是代理故障/故障转移,这些队列都将永久消失。当您的某个消费者试图回复这些队列时,其他代理都不会理解这是什么意思;因此您会出现异常。

这需要在思维方式上进行架构转变,假设您想要处理故障转移并持久化所有消息。以下是解决问题的一般方法:

  1. 你的回复报头应该引用一个特定于请求者进程的队列:例如queue:response.<client id>。如果您的客户端数量有限,则客户端id可能是一个标准名称,如果您有大量客户端,则可能是一个UUID。
  2. 出站消息应该设置相关标识符(只是一个允许您将请求与响应相关联的字符串-毕竟请求者可能会同时发出多个请求)。这是在JMSCorrelationID头中设置的,应该从请求复制到响应消息。
  3. 请求者需要在该队列上设置一个侦听器,该侦听器将根据该关联id将消息体返回给请求线程。为此需要编写一些多线程代码,因为您需要手动管理相关ids到发起线程的映射(可能是通过Futures )。

这与Apache Camel针对request-response over messaging所采取的方法类似。

要注意的一件事是,当客户端离开时,队列不会消失,因此您应该设置响应消息的生存时间,以便在未使用消息时将其从代理中删除,否则将获得未使用消息的积压。您还需要设置一个dead letter queue strategy to automatically discard expired messages

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6432672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档