Priority Queue Support
RabbitMQ has priority queue implementation in the core as of version 3.5.0.
You can declare priority queues using the
x-max-priority argument. This argument should be an integer indicating the maximum priority the queue should support. For example, using the Java client:
Channel ch = ...; Map<String, Object> args = new HashMap<String, Object>(); args.put("x-max-priority", 10); ch.queueDeclare("my-priority-queue", true, false, false, args);
You can then publish prioritised messages using the
priority field of
basic.properties. Larger numbers indicate higher priority.
Because the on-disk format for a priority queue is different, priority queues can only be defined by arguments, not policies. Queues can never change the number of priorities they support.
The AMQP 0-9-1 spec is a bit vague about how priorities work. It says that all queues MUST support at least 2 priorities, and MAY support up to 10. It does not define how messages without a priority property are treated.
In contrast to the AMQP 0-9-1 spec, RabbitMQ queues by default do not support priorities. When creating priority queues, you can specify as many priority levels as you like. Note that:
- There is some in-memory and on-disk cost per priority level per queue. There is also an additional CPU cost, especially when consuming, so you may not wish to create huge numbers of levels.
- The message
priorityfield is defined as an unsigned byte, so in practice priorities should be between 0 and 255.
Messages without a
priority property are treated as if their priority were 0. Messages with a priority which is higher than the queue’s maximum are treated as if they were published with the maximum priority.
It’s important to understand how consumers work when working with priority queues. By default, consumers may be sent a large number of messages before they acknowledge any, limited only by network backpressure.
So if such a hungry consumer connects to an empty queue to which messages are subsequently published, the messages may not spend any time at all waiting in the queue. In this case the priority queue will not get any opportunity to prioritise them.
In most cases you will want to use the
basic.qos method in manual acknowledgement mode on your consumers, to limit the number of messages that can be out for delivery at any time and thus allow messages to be prioritised.
In general priority queues have all the features of standard RabbitMQ queues: they support persistence, paging, mirroring, and so on. There are a couple of interactions that should be noted though:
- Messages which should expire will still only expire from the head of the queue. This means that unlike with normal queues, even per-queue TTL can lead to expired lower-priority messages getting stuck behind non-expired higher priority ones. These messages will never be delivered, but they will appear in queue statistics.
- Queues which have a max-length set will, as usual, drop messages from the head of the queue to enforce the limit. This means that higher priority messages might be dropped to make way for lower priority ones, which might not be what you would expect.