Passive or active queues?

In the previous RabbitMQ examples I have written, I have always declared queues calling Channel.queueDeclare(). But it is also possible to do it calling Channel.queueDeclarePassive(). As you could easily guess, the first method is for an active queue declaration, and the second for a passive one. The point of this post is: what a passive queue is and how to choose between declaring a queue as passive or active.

If you play with queue setting, one day or another you will end up getting an exception, due to the fact that once a queue is created, you can't access it specifying a different setting:
java.io.IOException
    at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:106)
    at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:102)
    at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:124)
...    
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error;
 reason: {#method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - 
 parameters for queue 'ack' in vhost '/' not equivalent, class-id=50, method-id=10),
 null, "[B@19d3b3a"}
    at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
...
In this case I tried to access a queue called "ack", declared in the default virtual host, passing the parameter "autodelete" set to true, where it was created with false.

When this happens, you could have a look to the RabbitMQ administrator, specifically in the Queues tab, to get all the available information on your queue.

But back to the main theme of the post.

If a queue is declared passively, RabbitMQ assumes it already exists, and we just want to establish a connection to it. What if you call Channel.queueDeclarePassive() and the queue is not there? I guess you already know the answer, you get a fat exception:
java.io.IOException
    at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:106)
    at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:102)
    at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:124)
...
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error;
 reason: {#method<channel.close>(reply-code=404, reply-text=NOT_FOUND -
 no queue 'ack' in vhost '/', class-id=50, method-id=10), null, "[B@140fee"}
    at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
...
Close to the exception shown above, but here the reply text is a NOT_FOUND that shows clearly what the problem is. Rabbit was running happily assuming the queue was there, but actually it wasn't.

So, we use a passive queue declare when we can safely assume the queue is already there, and its non-existence would considered an exceptional, almost catastrophic, event.

The safer active queue declaration has the obvious downside of being more expensive, and requiring the user to provide the setting each time a queue declaration is issued. An hybrid approach (active on the server, passive on the client) could make sense if the application has a rigid protocol ensuring that a component would always start before the other(s).

2 comments:

  1. thank you very much. your tips help a lot and solved my issues.

    ReplyDelete