What is the RabbitMQ prefetch count?
The short answer: The RabbitMQ prefetch value is used to specify how many messages are being sent at the same time.
Messages in RabbitMQ are pushed from the broker to the consumers. The RabbitMQ default prefetch setting gives clients an unlimited buffer, meaning that RabbitMQ, by default, sends as many messages as it can to any consumer that appears ready to accept them. It is, therefore, possible to have more than one message "in flight" on a channel at any given moment.
Messages are cached by the RabbitMQ client library (in the consumer) until processed. All pre-fetched messages are invisible to other consumers and are listed as unacked messages in the RabbitMQ management interface.
An unlimited buffer of messages sent from the broker to the consumer could lead to a window of many unacknowledged messages. Prefetching in RabbitMQ simply allows you to set a limit of the number of unacked (not handled) messages.
There are two prefetch options available, channel prefetch count and consumer prefetch count.
Channel Prefetch Count and Consumer Prefetch Count
The channel prefetch value defines the max number of unacknowledged deliveries that are permitted on a channel. Setting a limit on this buffer caps the number of received messages before the broker waits for an acknowledgment.
Because a single channel may consume from multiple queues, coordination between them is required to ensure that they don’t pass the limit. This can be a slow process especially when consuming across a cluster, and it is not the recommended approach.
The best practice is to set a consumer prefetch by setting a limit on the number of unacked messages at the client.
Please note that the prefetch value does not have an impact if you are using
the
Basic.get
request, as we talked about in the previous article:
RabbitMQ basic consume vs RabbitMQ basic get
How do I set the prefetch count?
RabbitMQ uses AMQP version 0.9.1 by default. The protocol includes the quality
of service method
Basic.qos
for setting the prefetch count. RabbitMQ allows you to set either a channel
or consumer count using this method.
Consider the following Pika example:
connection = pika.BlockingConnection()
channel = connection.channel()
channel.basic_qos(10, global=False)
The
basic_qos
function contains the global flag. Setting the value to
false
applies the
count to each new consumer. Setting the value to
true
applies a channel
prefetch count to all consumers.
Most APIs set the global flag to
false
by default.
Optimizing the prefetch count requires that you are considering the number of consumers and messages your broker handles. There is a negligible amount of additional overhead. The broker must understand how many messages to send to each consumer instead of each channel.
What is the optimum consumer prefetch count?
A larger prefetch count generally improves the rate of message delivery. The broker does not need to wait for acknowledgments as often and the communication between the broker and consumers decreases. Still, smaller prefetch values can be ideal for distributing messages across larger systems. Smaller values maintain the evenness of message consumption. A value of one helps ensure equal message distribution.
A prefetch count that is set too small may hurt performance since RabbitMQ might end up in a state, where the broker is waiting to get permission to send more messages. The image below illustrates a long idling time. In the figure, we have a QoS prefetch setting of one (1). This means that RabbitMQ won't send out the next message until after the round trip completes (deliver, process, acknowledge). Round-trip time in this figure is in total 125ms with a processing time of only 5ms.
A large prefetch count, on the other hand, could take lots of messages off the queue and deliver all of them to one single consumer, keeping the other consumers in an idling state, as illustrated in the figure below:
How to set the correct prefetch value?
If you have one single or only a few consumers processing messages quickly, we recommend prefetching many messages at once to keep your client as busy as possible. If you have about the same processing time all the time and network behavior remains the same, simply take the total round trip time and divide by the processing time on the client for each message to get an estimated prefetch value.
In a situation with many consumers and short processing time, we recommend a lower prefetch value. A value that is too low will keep the consumers idling a lot since they need to wait for messages to arrive. A value that is too high may keep one consumer busy while other consumers are being kept in an idling state.
If you have many consumers and/or long processing time, we recommend setting the prefetch count to one (1) so that messages are evenly distributed among all your workers.
Please note that if your client auto-acks messages, the prefetch value will have no effect.
Avoid the usual mistake of having an unlimited prefetch, where one client receives all messages and runs out of memory and crashes, causing all the messages to be re-delivered.
More information about RabbitMQ prefetch can be found in this recommended RabbitMQ documentation.
Become acquainted with the prefetch count using your own managed RabbitMQ broker at CloudAMQP.