Direct Reply-to
Overview
Direct reply-to is a feature that allows RPC (request/reply) clients with a design similar to that demonstrated in tutorial 6 without requiring the creation of a reply queue.
Request-reply implementations where clients use explicitly declared queues, both long-lived client named and connection-specific exclusive queues, are just as valid as Direct Reply-to, and have their benefits, in particular for workloads with long-running tasks
Motivation
RPC (request/reply) is a popular pattern to implement with a messaging broker
like RabbitMQ. Tutorial 6 demonstrates its implementation
with a variety of clients. The typical way to do this is for RPC clients to
send requests that are routed to a long lived (known) server queue. The RPC server(s)
consume requests from this queue and then send replies to each client
using the queue named by the client in the reply-to
header.
Where does the client's queue come from? The client can declare a single-use queue for each request-response pair. But this is inefficient; even an unreplicated queue can be expensive to create and then delete (compared with the cost of sending a message). This is especially true in a cluster as all cluster nodes need to agree that the queue has been created, agree on its type, replication parameters, and other metadata.
Therefore, the client should create a single reply queue for multiple RPC requests.
The properties of this reply queue depend on the use case:
- Exclusive queues are commonly used when replies are consumed by a single client and deleted upon disconnection
- Non-exclusive long-lived queues are better suited for long-running tasks, ensuring replies persist even if the client disconnects temporarily
Direct reply-to eliminates the need for a reply queue. This benefits the request-reply implementations with short-lived queues and transient responses at the cost of giving up all control over how the responses are stored.
With Direct Reply-to, RPC clients will receive replies directly from their RPC server, without going through a reply queue. "Directly" here still means going through the same channel and a RabbitMQ node; there is no direct network connection between RPC client and RPC server processes.
How to Use Direct Reply-to
To use direct reply-to, an RPC client should:
Consume from the pseudo-queue
amq.rabbitmq.reply-to
in no-ack mode. There is no need to declare this "queue" first, although the client can do so if it wants.Set the
reply-to
property in their request message toamq.rabbitmq.reply-to
.
The RPC server will then see a reply-to
property
with a generated name. It should publish to the default exchange
(""
) with the routing key set to this value (i.e. just as if
it were sending to a reply queue as usual). The message will
then be sent straight to the client consumer.
If the RPC server is going to perform some expensive computation
it might wish to check if the client has gone away. To do this
the server can declare the generated reply name first on a
disposable channel in order to determine whether it still
exists. Note that even if you declare the "queue" with
passive=false
there is no way to create it; the
declare will just succeed (with 0 messages ready and 1 consumer)
or fail.
Caveats and Limitations
The RPC client must consume in the automatic acknowledgement mode. This is because there is no queue for the reply message to be returned to if the client disconnects or rejects the reply message.
The RPC client must use the same connection and channel for both consuming from
amq.rabbitmq.reply-to
and for publishing the request message.Reply messages sent using this mechanism are in general not fault-tolerant; they will be discarded if the client that published the original request subsequently disconnects. The assumption is that an RPC client will reconnect and submit another request in this case.
The name
amq.rabbitmq.reply-to
is used inbasic.consume
and thereply-to
property as if it were a queue; however it is not. It cannot be deleted, and does not appear in the management plugin orrabbitmqctl list_queues
.If the RPC server publishes with the mandatory flag set then
amq.rabbitmq.reply-to.*
is treated as not a queue; i.e. if the server only publishes to this name then the message will be considered "not routed"; abasic.return
will be sent if the mandatory flag was set.
When to Use Direct Reply-to
While clients should use long lived connections, direct reply-to is ideal for workloads with high connection churn, where clients establish a connection for a single RPC and disconnect immediately after. By avoiding the creation of queue metadata in the metadata store, direct reply-to can reduce overhead and latency.
For workloads with long-lived connections where clients perform multiple RPCs, the performance benefits of direct reply-to are not significant compared to classic queues. Modern RabbitMQ versions have optimized classic queues for low latency and minimal resource usage, making them similarly efficient in such scenarios.