First of all, let’s describe how basic.consume and basic.get are different from each other.
Consumers are lightweight clients that receive messages or batches of messages from the broker as they become available. A consumer registers with the server via basic.consume. Once registered, the broker pushes messages using basic.deliver which the consumer acknowledges unless the no-ack option is set. The response tells the broker to send more messages to the client.
The figure below illustrates an application that starts a queue consumer, once the consumer is started the client returns a consume-ok. Messages are then flowing in an asynchronous manner between the client and the broker.
basic.get gives direct access to a queue instead of setting up a consumer. The basic.get function uses a polling model for retrieving a message. The RabbitMQ client (the consuming application) sends a request to the server for a message which responds with either get-ok or get-empty. A get-empty response occurs when the queue is empty.
This method requires synchronization between the client and the broker. The server processes the request while the client awaits a result. basic.get is slow and forgoes the benefit of allowing the broker to manage message delivery.
The figure illustrates an application that requests new messages. The broker reply differently depending on if there is a message to deliver or not.
What are the disadvantages of basic.get?
Unless the system is being tested or a use case is being worked on that requires synchronized behavior, a basic.get command consumes an unnecessary amount of time and resources, as follows:
- Requires sending a request for a message to the broker
- A request must be resent until a message becomes available
- Results in applications that cannot make use of temporary queues
The process works in short-lived programs that run after a queue receives a message. However, in most circumstances, basic.consume should be used. A consumer is preferable even in systems where not many messages are sent, as messages may not always be available.
Why not use temporary queues with basic.get
Temporary queues are deleted after all consumers signal their completion or they become unreachable. A basic.get request has no impact on this type of queue since the queue has never had a consumer connected.
A queue set to auto-delete must wait for a consumer to connect before it can be deleted. Otherwise, the queue would stop to exist the moment it was created. It is recommended to use the time-to-live feature or exclusive queues instead while using basic.get.
What are the advantages of a RabbitMQ consumer?
There are multiple advantages to using a RabbitMQ consumer over a get request. A consumer:
- Is able to send many messages at once, by setting a prefetch count
- Allows the server to push messages as needed
- Takes advantage of multiple acknowledgments without worrying about whether all messages were delivered or not
- Avoids the process of sending requests and handling responses from the server.
In practice, consumers are faster than processing each message individually. A consumer is relatively inexpensive to create in comparison to the cost of using a get request repeatedly. The RabbitMQ client registers with the broker and waits for messages. Consumers can acknowledge receipt automatically and use a cancellation method to stop receiving messages.
Consumers are ideal even if you are processing just a few messages every now and then. There are multiple ways in RabbitMQ to pause the queue consumer. You can completely delete the consumer or hold off on acknowledging messages as long as your consumer remains active.
It is possible to set a prefetch count with consumers. Prefetch count specifies the number of messages to send before waiting for an acknowledgment. Setting the value to 0 lets the consumer drain the entire queue. Read more about prefetch here. It is not possible to prefetch messages with basic.get.
There is also the ability to batch acknowledge messages. Setting the multiple flag to true will acknowledge all messages received up to a given point.
Should I use a RabbitMQ Consumer or Basic Get?
As described, a basic.get request is expensive. Using the command repeatedly impacts the speed of RabbitMQ based applications. When deciding between using a RabbitMQ consumer or a basic.get request, lean towards a consumer unless you are testing or need to synchronize message consumption.
RabbitMQ documentation instructs us that, “Fetching messages one by one is highly discouraged as it is very inefficient compared to regular long-lived consumers. As with any polling-based algorithm, it will be extremely wasteful in systems where message publishing is sporadic and queues can stay empty for prolonged periods of time. When in doubt, prefer using a regular long-lived a consumer.”
Discover the difference in your own free tier from CloudAMQP, where you can experiment with these and other RabbitMQ features.