我使用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关闭,同样的错误再次引发。我该如何解决它?
答案 0 :(得分:1)
有open feature request for this。
这并不容易,因为消费者特别是长寿和失败会导致处理中断(迫使消费者关闭和重新连接)。
该框架不知道何时会成为"好的"时间去做。
您可以通过编程方式致电resetConnection()
上的CachingConnectionFactory
以强制进行故障恢复,但同样会影响现有消费者 。 (resetConnection()
已添加到1.5,在早期版本中调用destroy()
。
也就是说,不清楚为什么这样的故障恢复是必要的,因为第二台服务器可能是HA队列的新主服务器,无论如何它最好从那里消费。 / p>
默认情况下,只有一个连接用于所有客户端(在Spring AMQP中),将使用现有的故障转移连接,直到失败。
您可以配置连接工厂以向每个用户分发不同的连接,并将缓存大小设置为1,但这实际上违背了缓存的全部目的。
修改强>
另一种解决方案可能是编写另一个连接工厂,该工厂包装2个连接工厂实例(每个实例都配置了一个地址)。
然后,在createConnection()
方法中,您可以"测试"第一个连接并使用(如果可用)。
这将导致" new"用户(例如RabbitTemplate
)方法进行故障恢复,但它仍然没有解决监听器容器(消费者)的情况;你必须强制重置该连接才能使它们失败。