删除RabbitMQ 3+中不存在的队列不会产生预期的错误;为什么?

时间:2014-04-15 17:44:15

标签: rabbitmq protocols network-protocols amqp

上下文

我们使用RabbitMQ 2.8.5rabbitmq-c客户端。我们决定升级到RabbitMQ 3.2.4以利用新功能/稳定性/性能。

我们不做任何与RabbitMQ特别复杂的事情;我们拥有的最复杂的拓扑结构是备用交换,以及双节点镜像HA集群。其他一切都是标准队列和消费者。

我们有一些关于队列的创建/删除的逻辑,这些逻辑偶尔会尝试删除一个不存在的队列(一个已被系统中的另一个代理删除的队列)。在这些情况下,我们希望获得AMQP channel.close帧以响应删除尝试,包含404 NOT_FOUND或类似内容。

问题:

根据RabbitMQ 2.8.5的预期,删除不存在的队列失败。但是,当我们尝试删除针对RabbitMQ 3.2的不存在的队列时,没有任何反应。没有收到错误,频道保持打开状态,并收到queue.delete.ok帧。

删除交换,绑定等也会出现问题

但是,尝试使用不存在的队列会产生预期的404 NOT_FOUND错误。

我尝试过的事情:

  1. 我在沙箱中重复了所有测试,以确保我的客户端没有从其他代理交互中收到虚假/错误的帧。即使我的RabbitMQ服务器上有唯一的客户端,问题仍然存在。
  2. 我做的第一件事就是找出问题所在。如果不使用我们针对rabbitmq-c驱动程序的任何特定于业务的包装,我可以使用执行以下操作的脚本重现该问题。 RabbitMQ版本之间的行为仍然会发生变化。
    1. connect(host, user, port, vhost)
    2. channel_open(1)
    3. queue_delete(1, "does_not_exist", ) // nowait is defaulted to 0.
  3. 然后我尝试了另一个驱动程序。我下载了AnyEvent::RabbitMQ并制作了一个快速的Perl脚本,它完成了与我的C代码完全相同的一系列操作。行为与我的测试脚本相同。
  4. 由于两位司机都出错了,我使用Wireshark分析了各个RabbitMQ服务器之间的流量。我的客户端和旧的(2.8.5)RabbitMQ服务器之间的事务看起来像我期望的那样:在connecttunechannel.open调用之后,queue.delete出去了,包含404 NOT_FOUND错误代码的channel.close几乎立刻回来了。当我在RabbitMQ 3服务器上运行时,结果令人惊讶:响应中收到queue.delete.ok帧,message-count字段设置为0.通道保持打开状态,没有迹象表明我的删除请求无效。使用Perl客户端和C客户端时都是如此。
  5. 我还尝试分别为我用于测试的虚拟主机中的所有队列打开和关闭HA /镜像。问题没有改变。
  6. 问题:

    为什么RabbitMQ 3确认删除不存在的队列,以及如何获得旧行为(由于无效操作导致的通道关闭错误)?

1 个答案:

答案 0 :(得分:1)

为了解决这个问题,我基本上在我们使用的所有RabbitMQ版本和最新版本之间进行了二进制搜索。

我最终发现这个功能是作为RabbitMQ主线enhancement 25716的一部分故意添加的,版本为3.2.0。

正如@ zaq178miami在评论中指出的那样(非常有用,谢谢!),RabbitMQ主站点上的规范违规也在此时更新。

关于此理由的讨论在RabbitMQ邮件列表here上进行。

虽然这种行为更多" AMQP-ish"比以前的行为,我需要进行一些重构,以使我现有的代码能够与更新版本的RabbitMQ一起使用

感谢上面的所有评论。对于未来的读者:这些评论包含有关此问题的其他有用链接。