On the first glance, RabbitMQ queues are very similar to MSMQ queues. First important difference is that you can’t change queue properties once a queue is created. There’s a way around that using policies, and we’ll talk about them later. Also, RabbitMQ queues don’t have subqueues or journals.
Each queue has only these two mandatory settings (flags):
- Durable – queue or exchange will survive broker restart. Otherwise, it won’t be available after restart – this doesn’t only apply to its messages but to entire queue. And if queue is durable it still doesn’t mean its messages will survive restarting – to achieve that they should be created as “Persistent”. This is similar to “recoverable” MSMQ messages.
- Auto delete – these queues exist only while there are consumers for them. When the last subscriber unsubscribes, queue is automatically deleted.
Additional queue properties
There are additional settings you can set for a queue when it’s created, which configure its behavior in more details. These settings are key-value pairs – a setting name and its value. Since these are free entries you can put anything you want there. However, there are some predefined settings which all queues recognize, and they start with “x-“. And some plugins might support their own properties. If you don’t set one of predefined properties, that value will be taken from the policy, if there is a policy applicable to a queue. We’ll deal with policies later.
Here are some of settings available for all queues:
- x-message-ttl – how long to keep message while it waits processing. If it times out, message will be deadlettered. This applies to all messages in a queue. You can also set expiration time for individual message separately, and that parameter is similar to MSMQ’s Time to live message property.
- x-max-length and x-max-length-bytes – max size of queue. MSMQ can specify that only in kilobytes, but RabbitMQ can limit both number of messages and their total size.
- x-max-priority – message priorities are not a predefined set like in MSMQ, but numbers.
Message is moved to deadletter in few cases: when it’s rejected by receiving application (by calling basic.reject or basic.nack without requeue option), when it expires because of “Time to live” setting, or if queue limit is exceeded. There are no system deadletter queues like in MSMQ, so you have to create your own and instruct RabbitMQ to use them for deadlettered messages. Or, to be more precise, you specify dead letter exchange since we always send to exchanges, not to queues.
Since this is configurable for each queue, you can set it up that each important queue has separate deadletter exchange, or it can be shared by multiple queues. When messages end up in deadletter they’ll have x-first-death-queue header set to original queue, so even if deadletter is shared you’ll know where they came from.
Deadlettered message gets additional data in its headers – fields starting with “x-death”, which describe the reason for deadlettering, original queue, time, etc. QueueExplorer allows you to see these details:
Deadlettering is turned on for a queue by adding “x-dead-letter-exchange” to queue’s properties, or to a policy which is applied to that queue. Optionally, you can specify “x-dead-letter-routing-key” which will be used instead of message’s original routing key. Dead letter exchange is like any other exchange, you specify its type and bindings.
In the next part we’ll see what are policies and how to use them.
Links to all 6 parts of this series.