سؤال

Context:

We use RabbitMQ 2.8.5, and the rabbitmq-c client. We decided to upgrade to RabbitMQ 3.2.4 to take advantage of new features/stability/performance.

We don't do anything particularly complicated with RabbitMQ; the most complicated topological construct we have is an alternate exchange, and a two-node mirrored HA cluster. Everything else is standard queues and consumers.

We have some logic regarding the creation/deletion of queues that will occasionally try to delete a non-existent queue (one that has been deleted by another agent in the system). In those cases, we expect to get an AMQP channel.close frame in response to the deletion attempt, containing 404 NOT_FOUND or similar.

Problem:

Deletion of nonexistent queues fails as expected against RabbitMQ 2.8.5. However, when we try to delete a nonexistent queue against RabbitMQ 3.2, nothing happens. No error is received, the channel stays open, and a queue.delete.ok frame is received.

The problem also occurs with the deletion of exchanges, bindings, etc.

Attempting to consume a nonexistent queue, however, yields the expected 404 NOT_FOUND error.

What I've Tried:

  1. I repeated all of my tests in a sandbox to ensure that my clients weren't receiving spurious/wrong frames from other broker interactions. Even when mine were the only clients on the RabbitMQ servers in question, the issue persisted.
  2. The first thing I did was to isolate the problem. Without using any of our business-specific wrapping around the rabbitmq-c driver, I can reproduce the issue with a script that does the following. The behavior still changes between RabbitMQ versions.
    1. connect(host, user, port, vhost)
    2. channel_open(1)
    3. queue_delete(1, "does_not_exist", ) // nowait is defaulted to 0.
  3. Then I tried another driver. I downloaded AnyEvent::RabbitMQ and made a quick Perl script that did the exact same series of operations as my C code did. The behavior was identical to that of my test script.
  4. Against the chance that both drivers were doing something wrong, I analyzed the traffic to and from the respective RabbitMQ servers using Wireshark. The transaction between my client and the old (2.8.5) RabbitMQ server looked the way I expected it to: after connect, tune, and channel.open calls, a queue.delete went out, and a channel.close containing the 404 NOT_FOUND error code came back near-instantly. When I ran it against the RabbitMQ 3 server, the results were surprising: a queue.delete.ok frame was received in response, with a message-count field set to 0. The channel remained open, with no indication that my deletion request was invalid. This was true when using the Perl client and the C client.
  5. I also tried turning HA/mirroring on and off, respectively, for all queues in the vhosts I was using for testing. The issue did not change.

Question:

Why is RabbitMQ 3 confirming deletes on nonexistent queues, and how can I get the old behavior (a channel closure error due to invalid operations) back?

هل كانت مفيدة؟

المحلول

To solve the problem, I basically did a binary search across all RabbitMQ versions between the one we were using and the latest one.

I eventually discovered that this functionality was deliberately added as part of RabbitMQ mainline enhancement 25716, in version 3.2.0.

As @zaq178miami pointed out in the comments (very informative, thanks!), the specification violations on the RabbitMQ main site were also updated at this time.

A discussion of the rationale for this is on the RabbitMQ mailing list, here.

While this behavior is more "AMQP-ish" than the previous behavior, it will require some refactoring on my part to make my existing code work with newer versions of RabbitMQ

Thanks for all the comments above. For future readers: those comments contain additional useful links regarding this issue.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top