RPC with RabbitMQ Direct Reply-to

RPC using the RabbitMQ direct reply-to header allows developers to create responsive applications. Perform tasks remotely from your mobile and desktop applications without additional services and costs.

An option in with RPC in RabbitMQ is to avoid creating a queue to wait on. RabbitMQ allows you to pass a response directly to the client instead. This article examines the ability of RabbitMQ to serve as a middle-man for a remote procedure call, using direct reply-to.

What is RPC?

In a remote procedure call, a client sends a request to run a function and any related arguments to a server specified in compiled code. The remote server runs the task and sends back the response.

Typically, the client code contains a stub referring to the server. The initiating program stalls until it receives a response.

RabbitMQ RPC

The RPC process works somewhat differently in RabbitMQ. There is no stub. The program will not stall if you use a non-blocking consumer either.

Your client sends a message to the broker containing the reply-to header. The target server processes the request and sends data back to the queue specified in the header. Just as in the PubSub model of RabbitMQ, your consumer receives the response.

Direct Reply

It is possible to avoid creating a queue to wait on. RabbitMQ allows you to pass a response directly to the client instead.

To do so, set reply-to to amq.rabbitmq.reply-to. Send a message in no-ack mode. RabbitMQ generates a special name that the target server sees as the routing key. The remote machine then publishes the result to the default exchange. No queue is created in the process.

When to Use Direct Reply

A direct reply allows you to avoid maintaining a long-lived queue. It also lets you avoid creating short-lived queues that utilize memory.

There are some pitfalls when using a direct reply. RabbitMQ does not create a queue for each request. The generated name is not attached to a queue. Any undelivered messages are discarded as well.

The direct reply is not beneficial if you need to save a response or want to collect metrics to help tune your broker or hardware. You will want to use RPC with an actual queue in this case.

Another factor to consider is the speed of RabbitMQ. RabbitMQ RPC performance is no better than the broker itself. The system performs well for processing small batches of data or when writing a mobile application. It is not meant to process a massive amount of data over many requests.

Using Direct Reply-to in RabbitMQ

To use the direct reply feature, use the reply-to header with the amq.rabbitmq.reply-to queue. In this RPC example, we send a simple ping request to a remote machine.

Start by consuming from the amq.rabbitmq.reply-to queue on your client to avoid missing the response:

def client_consumer_callback(ch, method, properties, body):
  msg = body.decode('utf-8')
  if msg in "Hello from Consumer":
      print("TARGET MACHINE IS ACTIVE")
      global RECEIVED_HELLO
      RECEIVED_HELLO = True
  else:
      print("RECEIVED UNEXPECTED MESSAGE")
  ch.close()
channel.consume("amq.rabbitmq.reply-to", on_message_callback=client_consumer_callback)

The consumer checks that the response message contains a greeting from the server.

Next, create another consumer to mimic a remote computer:

def consumer_callback(ch, method, properties, body):
  msg = body.decode('utf-8')
  if msg in "Hello World":
      basic_props = BasicProperties()
      ch.basic_publish(exchange='', routing_key=properties.reply_to, properties=basic_props,    body="Hello from Consumer")
      ch.basic_ack(delivery_tag=method.delivery_tag)
  else:
      print("RECEIVED UNEXPECTED MESSAGE")
channel.consume("amq.rabbitmq.reply-to", on_message_callback=consumer_callback)

This consumer receives the request, checks that the message contains Hello World, and sends back a greeting. Notice that both consumers subscribe to amq.rabbitmq.reply-to.

Finally, send a message to the queue using the reply-to header:

basic_props = BasicProperties(
    reply_to="amq.rabbitmq.reply-to"
)

channel.basic_publish('', routing_key="", properties=basic_props, body="Hello World")

You can use this method to fetch data or perform tasks such as registering users on a mobile application. We created a simple health check.

Tips for Using a Direct Reply

RPC with direct reply-to differs somewhat from the traditional publisher-subscriber model RabbitMQ is known for. No queues are created and the process sends information directly to the client using a direct reply.

When using RPC this way, keep following in mind:

  • Try to establish a connection to the client using the generated name on a disposal channel to see if the client still exists
  • Set the immediate flag to false when publishing
  • Start consuming from the amq.rabbitmq.reply-to before publishing your message
  • Set the mandatory flag if using amq.rabbitmq.reply-to to create error logs
  • Do not set the mandatory flag when using a direct-reply if using amq.rabbitmq.reply-to.* as your queue

These tips allow you to know when something goes wrong. They also help you handle issues without losing messages.

Building Responsive Applications with RabbitMQ

The direct reply in RabbitMQ lets you create applications that communicate with one another over a special form of RPC. Use this process to your advantage alongside the RabbitMQ direct reply-to header to cut down on development time and avoid the cost of implementing a new system.

CloudAMQP allows you to create a free broker to test whether this feature is right for your application. Create your RabbitMQ broker for free and start sending messages today.

CloudAMQP - industry leading RabbitMQ as a service

Start your managed cluster today. CloudAMQP is 100% free to try.

13,000+ users including these smart companies