57

Does RabbitMQ have any concept of message priority? I have an issue where some more important messages are being slowed down due to less important messages sitting before them in the queue. I want the high-priority ones to take precedence and move to the front of the queue.

I know I can approximate this using two queues, a "fast" queue and a "slow" queue, but that seems like a hack.

Does anyone know of a better solution using RabbitMQ?

TarHalda
  • 1,050
  • 1
  • 9
  • 27
Kelly
  • 6,992
  • 12
  • 59
  • 76
  • 4
    pretty sure the point of a queue is that its FIFO, therefore there concept of priority goes out the window. – robthewolf May 24 '12 at 21:16
  • 1
    Many technologies such as ActiveMQ have a message priority concept as well. This lets the queue be a hybrid FIFO/Priority queue. – Kelly May 25 '12 at 20:40

8 Answers8

94

The answers on this question are out-of-date. As of RabbitMQ 3.5.0, there is now in-core support for AMQP standard per-message priorities. The documentation has all the gory details, but in short:

  • You need to define the queue's priority range at the time the queue is created;
  • Messages without a priority set get a priority of 0;
  • Messages with a numeric priority higher than the maximum set on the queue get the highest priority the queue supports.

More interesting caveats are in the docs. It's well worth reading them.

womble
  • 12,033
  • 5
  • 52
  • 66
  • hello @Womble, I've read the doc and had a bit of trouble implementing it. Other documentation is pretty sparse. If you've got any insight. My question is [here](http://stackoverflow.com/questions/29221020/rabbitmq-3-5-and-message-priority) – Ommit Mar 24 '15 at 15:22
  • 3
    it seems it is not a message priority but consumer priority, which I think are different concepts and not answers to above question. – Kostanos Jan 05 '17 at 00:46
  • Changed this to the correct answer since RabbitMQ now supports priority queues. – Kelly Feb 08 '17 at 02:10
  • 1
    One thing about RabbitMq message priorities is that consumers are hungry. If you publish a load of messages with different priorities then they will tend towards the priority, but it isn't exactly guaranteed because the receive endpoint gets messages as they arrive. Another way to do this is to have two consumers with different max priorities enabled. The one with the higher max will process all messages, whilst the lower priority consumer will process only up to that max setting. – Rebecca Nov 22 '18 at 09:27
  • How to set priority for consumer, who have to get message first or last? – POV Dec 18 '18 at 21:20
20

Rabbit has no concept of priority other than, as Brian succinctly puts it, the one in front gets there first. ;-)

I would suggest implementing a set of queues that serve to service your particular messaging need and have these queues model your prioritisation need by, say, calling them 'MyQueueP1', 'MyQueueP2' and so on and then have our consumer(s) check P1 before P2 (etc.) and service messages from there first.

If you then have a message that is high priority you would publish it to the appropriate priority queue by way of a suitable routing key and voila.

[update] Check this question: In a FIFO Qeueing system, what's the best way the to implement priority messaging

[update] As per recent RabbitMQ release 3.5.0 this answer is now outdated and should be considered valid for only versions prior to this release. https://stackoverflow.com/a/29068288/489888

Community
  • 1
  • 1
Steve Martin
  • 1,632
  • 10
  • 19
  • Thanks for the reply, I was hoping to avoid setting up multiple queues for this but it looks like it the way to go. – Kelly May 25 '12 at 20:43
  • 1
    Some info from [www.rabbitmq.com/api-guide.html] : Section **Publishing messages** : This sends a message with delivery mode 2 (persistent), priority 0 and content-type "text/plain". You can build your message properties object, using a Builder class mentioning as many properties as you like, for example: channel.basicPublish(exchangeName, routingKey, new AMQP.BasicProperties.Builder() .contentType("text/plain").deliveryMode(2) .priority(1).userId("bob") .build()), messageBodyBytes); – user2602807 Jan 05 '15 at 19:51
  • But there is no other explanation about "priority", and what do they mean – user2602807 Jan 05 '15 at 19:51
  • 1
    As of 3.5.0 - RabbitMQ supports priority queues: http://www.rabbitmq.com/priority.html – ferrouswheel Mar 18 '15 at 01:48
  • is it only the java implementation that works? I'm struggling to make it work in C#. I've asked a question here: [http://stackoverflow.com/questions/29221020/rabbitmq-3-5-and-message-priority?lq=1](http://stackoverflow.com/questions/29221020/rabbitmq-3-5-and-message-priority?lq=1) – Ommit Mar 26 '15 at 20:11
  • This answer is out-of-date. As it is the accepted answer, would you mind updating it to reflect the current state? – womble Mar 27 '15 at 01:13
  • @womble, I did, 9 days ago :-) – Steve Martin Mar 27 '15 at 09:44
  • The opening sentence says "Rabbit has no concept of priority". This is incorrect. – womble Mar 28 '15 at 07:08
  • @womble - I agree, though this was correct at the time of posting. The answer remains as is in order to preserve the context. I have appended an update indicating that the answer is no longer relevant. I'm pretty sure that folk are able to follow this. Feel free to flag this with a community moderator if you feel that my actions aren't sufficient. – Steve Martin Mar 30 '15 at 08:14
10

IIRC RabbitMQ still uses the AMQP protocol version 0.9.1 (get the spec here). The spec definitely mentions message priority:

Messages may have a priority level. A high priority message is sent ahead of lower     priority messages
waiting in the same message queue. When messages must be discarded in order to maintain a specific
service quality level the server will first discard low-priority messages.

And:

Note that in the presence of multiple readers from a queue, or client transactions, or use of priority fields,
or use of message selectors, or implementation-specific delivery optimisations the queue MAY NOT
exhibit true FIFO characteristics.

The spec says priority is a MUST, so I guess RabbitMQ should implement it, but you may want to consult its documentation.

vanza
  • 9,715
  • 2
  • 31
  • 34
  • 1
    This answer was incorrect until a week ago when RabbitMQ 3.5.0 was released and announced support for priority queues ;-) – ferrouswheel Mar 18 '15 at 01:56
6

Yes, RabbitMQ supports priority queues.

To make a queue work as a priority queue, supply property x-max-priority when declaring the queue.

Property x-max-priority defines the maximum priority number the queue supports.

In Java, you can do like below:

Map<String, Object> props = new HashMap<>();
props.put("x-max-priority", 10); // max priority number as 10
channel.queueDeclare(QUEUE_NAME, durable, false, false, props);

To publish messages of a particular priority, do like below:

String message = "My message with priority 7";
AMQP.BasicProperties.Builder basicProps = new AMQP.BasicProperties.Builder();
basicProps.contentType("text/plain")
            .priority(7);
channel.basicPublish("", QUEUE_NAME, basicProps.build(), message.getBytes());
Liquidpie
  • 1,589
  • 2
  • 22
  • 32
0

Here's a C# code sample that defines a queue with a range of priorities:

using RabbitMQ.Client;
public void Setup()
{
    ConnectionFactory factory = new() { host = "", username = "", password = "" };
    var connection = factory.CreateConnection();
    var model = connection.CreateModel();
    var args = new Dictionary<string, object>
    {
        { "x-min-priority", 0 },
        { "x-max-priority", 9 }
    };
    model.QueueDeclare("Queue1", arguments: args);
}

And here's a function for sending messages with priority:

private static void Send(IModel model, string queue, string message, byte priority)
{
    var body = Encoding.UTF8.GetBytes(message);

    var basicProperties = model.CreateBasicProperties();
    basicProperties.Priority = priority;

    model.BasicPublish(exchange: "",
                       routingKey: queue,
                       basicProperties: basicProperties,
                       body: body);
}

As mentioned by other people, Rabbit doesn't strictly obey these priorities.

If you send a message outside the range defined for the queue, it's treated as the min or max value.

Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
-1

We could make rabbitmq a distributed priority queue by installing the plugin rabbitmq_priority_queue from https://www.rabbitmq.com/community-plugins.html . You have to download the plugin rabbitmq_priority_queue-3.3.x-72d20292.ez and put inside plugins folder of your rabbit mq installation directory. Restart the server. Now you can insert items into the queue with a priority and consume it accordingly , have pasted the sample code in How to poll the RabbitMQ to get messages in order of priority continuously? .

Community
  • 1
  • 1
Ranjith
  • 475
  • 6
  • 17
-5

RabbitMQ / AMQP definitely has a concept of message priority - the message at the head of a queue gets priority over the one behind it, and that one gets priority over the one behind it, and so on, ad infinitum.

Can you change that model? Nope! :)

Brian Kelly
  • 19,067
  • 4
  • 53
  • 55
-12

If it implemented prioritization, it would not be an MQ.

MQs are email for data. And in all data transmission preserving order is vital. If you switch order, deletes happen before inserts, updates get out of sequence. Nothing works properly.

You may have a valid implementation, there are a few exceptions, but I have found that most priority queues are designed because people are thinking shallow thoughts about their system architecture and the interactions of the parts therein. Preserving the order of things is almost always the right thing to do, both for in-entity, and inter-entity interactions.

In order to say an event A can have a priority higher than event B, the two events must be de-coupled always. And when that happens one wonders why they exist in the same queue structure at all. Then again, if it is payload related, the calculation effort for that payload is also going to impact the performance of the system, so deciding sooner, ie before making the payload makes sense.

Michael
  • 587
  • 3
  • 14
  • 4
    There are plenty of message queues (HornetQ, ActiveMQ...etc) that implement message priority and plenty of use cases that support it. – Keith P Nov 12 '13 at 14:50
  • In effect these are simply logical extensions of the idea of independent queues. The term priority seldom has any real meaning as far as the pipeline goes. It is semantic sugar. I didnt say dont use them, I said it is a potential trap to be aware of. Many programmers presume that high priority means faster execution time. When they have a coupled process they figure put it in the low priority queue and that is good enough. If it works much of the time it is accepted and adopted as correct. Then systems start to fail unaccountably and it is horrible to debug. – Michael Feb 20 '15 at 20:42
  • Tangential, but I don't see how email would guarantee order of delivery. In fact, email *does* have (crude) transport priorities, by way of the `Precedence:` header. – tripleee Aug 24 '16 at 02:48
  • Oh how the turntables – user37309 Jul 23 '22 at 15:29