我正在尝试解决RabbitMQ中的竞争状况,该状况与服务器在网络/套接字断开连接后未及时获取独占队列有关,并导致客户端中的恢复代码失败。这不是我设计或编写的代码,对RabbitMQ和Spring来说我是新手。我们还使用了较旧的spring-rabbit版本1.7.0.RELEASE,因此我无法使用许多新功能来解决此问题。可以选择升级到最新代码,但需要全套回归测试,我们希望将其作为一种短期解决方案来简化,以便我们能够迅速出手。然后,我们可以将升级和所需的更改滚动到更高的版本中,以便有时间对其进行适当的测试。
问题很简单。我们有一个Java服务器应用程序,它创建一个命名队列,所有客户端都可以将消息发送到该队列。我们的java客户端各自创建一个命名的(基于主机的名称)排他的自动删除队列,以接收来自服务器的消息。之所以将其设置为独占,是因为我们不希望任何其他客户端使用相同的队列,因为发送到该队列的所有消息都是针对创建该队列的客户端的。我知道创建这样的命名排他队列是一个坏主意,并且服务器生成的队列名称是首选,但这是系统的实现方式,现在要对其进行修复,需要进行许多向后不兼容的更改和更多的测试... >
该问题发生在套接字连接断开的网络故障上。客户端检测到此情况,并尝试重新建立连接和队列等。似乎存在一种竞争状况,在此情况下,RabbitMQ服务器在客户端尝试重试多次创建队列之前,没有获得现有队列,并已关闭连接。 RabbitMQ服务器最终确实会获得队列,但是到那时客户端已经失败并且无法恢复。
要解决此问题,我尝试创建非独占队列,并将使用者设置为独占(实际上已经存在)。效果很好,可以解决比赛条件。但是,使队列不是互斥的会在由互斥队列避免的错误情况下引起严重的副作用。如果第二个客户端(client2)的配置不正确,并尝试使用另一个客户端(client1)已经使用的队列名,则队列创建失败,但是连接保持打开状态,因此client2仍然可以向服务器发送消息,就像是client1。
队列的排他性导致连接失败,从而破坏了整个连接,并使client2无法在任何方向上与Rabbit服务器通信。删除队列专有权并依靠使用者专有权意味着client2不能使用来自client1队列的任何消息,但仍可以像我们的client1一样向我们的服务器发送消息。当服务器从两个不同的客户端获取冲突的状态信息时,这会导致client1的控制严重中断。
短期内,我想做的是尝试检测client2上的Queue创建失败,并关闭连接,就像排他队列失败时发生的情况一样,这样client2就会失败,但是也不会导致client1失败。但是,我不知道该怎么做才能检测到故障。有没有办法做到这一点?在文档或Spring AMQP代码中,我似乎都找不到任何内容。
建议?
答案 0 :(得分:0)
首先,1.7.0已有两年历史了;在编写1.7.13时,您至少应使用最新的1.7.x。
SimpleMessageListenerContainer
具有属性missingQueuesFatal
,默认情况下为true。如果设置为false
,则容器应继续无限期尝试。