简体   繁体   English

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

[英]ActiveMQ: How to handle broker failovers while using temporary queues

On my JMS applications we use temporary queues on Producers to be able to receive replies back from Consumer applications. 在我的JMS应用程序上,我们在Producers上使用临时队列,以便能够从Consumer应用程序接收回复。

I am facing exactly same issue on my end as mentioned in this thread: http://activemq.2283324.n4.nabble.com/jira-Created-AMQ-3336-Temporary-Destination-errors-on-HA-failover-in-broker-network-with-Failover-tt-td3551034.html#a3612738 我在这个主题中提到的完全相同的问题: http//activemq.2283324.n4.nabble.com/jira-Created-AMQ-3336-Temporary-Destination-errors-on-HA-failover-in -broker-网络与故障转移-TT-td3551034.html#a3612738

Whenever I restarted an arbitrary broker in my network, I was getting many errors like this in my Consumer application log while trying to send reply to a temporary queue: 每当我在网络中重新启动一个任意代理时,在尝试将回复发送到临时队列时,我在使用者应用程序日志中收到了许多这样的错误:

javax.jms.InvalidDestinationException:
  Cannot publish to a deleted Destination: temp-queue://ID:...

Then I saw Gary's response there suggesting to use 然后我看到加里在那里建议使用的回应

jms.watchTopicAdvisories=false

as a url param on the client brokerURL . 作为客户端brokerURL上的url参数。 I promptly changed my client broker URLs with this additional parameter. 我使用此附加参数立即更改了客户端代理URL。 However now I am seeing errors like this when I restart my brokers in network for this failover testing: 但是现在,当我在网络中重新启动我的代理进行此故障转移测试时,我发现这样的错误:

javax.jms.JMSException: 
  The destination temp-queue:
    //ID:client.host-65070-1308610734958-2:1:1 does not exist.

I am using ActiveMQ 5.5 version. 我使用的是ActiveMQ 5.5版本。 And my client broker URL looks like this: 我的客户端代理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

Additionally here is my activemq config XML for one of the 4 brokers: amq1.xml 另外,这是我的4个代理之一的activemq配置XML: amq1.xml

Can someone here please look into this problem and suggest me what mistake I am making in this setup. 有人可以在这里查看这个问题并建议我在这个设置中犯了什么错误。

Update: 更新:

To clarify further on how I am doing request-response in my code: 为了进一步澄清我在代码中如何进行请求 - 响应:

  1. I already use a per producer destination (ie temporary queue) and set this in reply-to header of every message. 我已经使用了每个生产者目的地(即临时队列)并在每个消息的回复标题中设置它。
  2. I am already sending a per message unique correlation identifier in JMSCorrelationID header. 我已经在JMSCorrelationID标头中发送了每条消息唯一的相关标识符。
  3. As far as I know even Camel and Spring are also using temporary queue for request-response mechanism. 据我所知,即使Camel和Spring也使用临时队列进行请求 - 响应机制。 Only difference is that Spring JMS implementation creates and destroys temporary queue for every message whereas I create temporary queue for the lifetime of the producer. 唯一的区别是Spring JMS实现为每条消息创建和销毁临时队列,而我在生产者的生命周期中创建临时队列。 This temporary queue is destroyed when client (producer) app shutsdown or by the AMQ broker when it realizes there are no active producer attached with this temporary queue. 当客户端(生产者)应用程序关闭时,或者当AMQ代理意识到没有与此临时队列连接的活动生成器时,将销毁此临时队列。
  4. I am already setting a message expiry on each message on Producer side so that message is not held up in a queue for too long (60 sec). 我已经在生产者端的每条消息上设置了消息到期,这样消息就不会在队列中停留太长时间(60秒)。

There is a broker attribute, org.apache.activemq.broker.BrokerService#cacheTempDestinations that should help in the failover: case. 有一个代理属性org.apache.activemq.broker.BrokerService #cacheTempDestinations应该有助于故障转移:case。 Set that to true in xml configuration, and a temp destination will not be removed immediately when a client disconnects. 在xml配置中将其设置为true,并且在客户端断开连接时不会立即删除临时目标。 A fast failover: reconnect will be able to producer and/or consume from the temp queue again. 快速故障转移:重新连接将能够再次从临时队列生成和/或使用。

There is a timer task based on timeBeforePurgeTempDestinations (default 5 seconds) that handles cache removal. 有一个基于timeBeforePurgeTempDestinations(默认为5秒)的计时器任务,用于处理缓存删除。

One caveat though, I don't see any tests in activemq-core that make use of that attribute so I can't give you any guarantee on this one. 但有一点需要注意,我没有在activemq-core中看到任何使用该属性的测试,因此我无法对此提供任何保证。

Temporary queues are created on the broker to which the requestor (producer) in your request-reply scenario connects. 在请求 - 应答方案中请求者(生产者)连接的代理上创建临时队列。 They are created from a javax.jms.Session , so on that session disconnecting, either because of client disconnect or broker failure/failover, those queues are permanently gone. 它们是从javax.jms.Session创建的,因此在该会话断开连接时,由于客户端断开连接或代理失败/故障转移,这些队列将永久消失。 None of the other brokers will understand what is meant when one of your consumers attempts to reply to those queues; 当你的一个消费者试图回复这些队列时,其他经纪人都不会理解其含义; hence your exception. 因此你的例外。

This requires an architectural shift in mindset assuming that you want to deal with failover and persist all your messages. 这需要在思维模式上进行架构转换,假设您要处理故障转移并保留所有消息。 Here is a general way that you could attack the problem: 以下是您可以解决问题的一般方法:

  1. Your reply-to headers should refer to a queue specific to the requestor process: eg queue:response.<client id> . 您的回复标题应该引用特定于请求者进程的queue:response.<client id>例如queue:response.<client id> The client id might be a standard name if you have a limited number of clients, or a UUID if you have a large number of these. 如果您的客户端数量有限,则客户端ID可能是标准名称;如果您拥有大量客户端,则客户端ID可能是UUID。
  2. The outbound message should set a correlation identifier (simply a sting that lets you associate a request with a response - requestors after all might make more than one request at the same time). 出站消息应该设置一个相关标识符(只是一个sting,它允许您将请求与响应相关联 - 请求者可能同时发出多个请求)。 This is set in the JMSCorrelationID header, and ought to be copied from the request to the response message. 这是在JMSCorrelationID标头中设置的,应该从请求复制到响应消息。
  3. The requestor needs to set up a listener on that queue that will return the message body to the requesting thread based on that correllation id. 请求者需要在该队列上设置一个侦听器,该侦听器将根据该相关ID将消息体返回给请求线程。 There is some multithreading code that needs to be written for this, as you'll need to manually manage something like a map of correlation ids to originating threads (via Futures perhaps). 有一些需要为此编写的多线程代码,因为您需要手动管理诸如相关ID的映射到原始线程(可能通过Futures)。

This is a similar approach to that taken by Apache Camel for request-response over messaging . 这与Apache Camel针对消息传递的请求 - 响应采用的方法类似。

One thing to be mindful of is that the queue will not go away when the client does, so you should set a time to live on the response message such that it gets deleted from the broker if it has not been consumed, otherwise you will get a backlog of unconsumed messages. 需要注意的一点是,当客户端执行时,队列不会消失,所以你应该设置一个时间来生成响应消息,这样如果没有消耗它就会从代理中删除,否则你会得到积压的未消耗的消息。 You will also need to set up a dead letter queue strategy to automatically discard expired messages . 您还需要设置死信队列策略以自动丢弃过期的消息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM