具有弹簧的Rabbitmq群集在故障转移后不会失败

时间:2015-09-14 07:47:51

标签: java spring rabbitmq spring-amqp

我使用spring-amqp连接到rabbitmq节点(A,B)的集群。此外,假设有两个消息接收器(Receiver_1和Receiver_2)正在使用与节点A的连接。

当A发生故障时,Receiver_1和Receiver_2会自动切换连接以连接到B.假设A出现,然后群集中的B关闭。但是接收器不能再次消耗A.为什么呢?

我调试了弹簧项目,发现它不是弹簧消费者的错误。实际上,spring确实会切换到服务器“A”,但会出现以下异常:

  

org.springframework.amqp.rabbit.listener.QueuesNotAvailableException:   无法为侦听器准备队列。队列不存在或   经纪人不允许我们使用它。在   org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:429)     在   org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer $ AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1022)     在java.lang.Thread.run(未知来源)引起:   org.springframework.amqp.rabbit.listener.BlockingQueueConsumer $ DeclarationException:   无法声明队列:[ha.rabbit.channel2] at   org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:486)     在   org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:401)     ......还有2个

我检查了rabbidmq中的日志文件:

  

=错误报告==== 2015年9月14日:: 03:45:41 ===连接时的通道错误< 0.289.0> (192.168.1.150:64140 - > 192.168.1.170:5672,   vhost:'/',user:'admin'),频道2:{amqp_error,not_found,               “vhost'/'中持久队列'ha.rabbit.channel2'的主节点'rabbit @ vm2'已关闭或无法访问”,               'queue.declare'}

即使我重新启动了消费者应用程序,而以前的配置只是服务器A启动且B关闭,同样的错误再次引发。我该如何解决它?

1 个答案:

答案 0 :(得分:1)

open feature request for this

这并不容易,因为消费者特别是长寿和失败会导致处理中断(迫使消费者关闭和重新连接)。

该框架不知道何时会成为"好的"时间去做。

您可以通过编程方式致电resetConnection()上的CachingConnectionFactory以强制进行故障恢复,但同样会影响现有消费者 。 (resetConnection()已添加到1.5,在早期版本中调用destroy()

也就是说,不清楚为什么这样的故障恢复是必要的,因为第二台服务器可能是HA队列的新主服务器,无论如何它最好从那里消费。 / p>

默认情况下,只有一个连接用于所有客户端(在Spring AMQP中),将使用现有的故障转移连接,直到失败。

您可以配置连接工厂以向每个用户分发不同的连接,并将缓存大小设置为1,但这实际上违背了缓存的全部目的。

修改

另一种解决方案可能是编写另一个连接工厂,该工厂包装2个连接工厂实例(每个实例都配置了一个地址)。

然后,在createConnection()方法中,您可以"测试"第一个连接并使用(如果可用)。

这将导致" new"用户(例如RabbitTemplate)方法进行故障恢复,但它仍然没有解决监听器容器(消费者)的情况;你必须强制重置该连接才能使它们失败。