Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a queue per remote method when using RabbitMQ?

Tags:

rabbitmq

rpc

mq

Let's just accept for a moment that it is not a horrible idea to implement RPC over message queues (like RabbitMQ) -- sometimes it might be necessary when interfacing with legacy systems.

In case of RPC over RabbitMQ, clients send a message to the broker, broker routes the message to a worker, worker returns the result through the broker to the client. However, if a worker implements more than one remote method, then somehow the different calls need to be routed to different listeners.

What is the general practice in this case? All RPC over MQ examples show only one remote method. It would be nice and easy to just set the method name as the routing rule/queue name, but I don't know whether this is the right way to do it.

like image 955
Mate Varga Avatar asked Jul 28 '15 21:07

Mate Varga


People also ask

Can RabbitMQ have multiple queues?

Use multiple queues and consumers Queues are single-threaded in RabbitMQ, and one queue can handle up to about 50 thousand messages. You will achieve better throughput on a multi-core system if you have multiple queues and consumers and if you have as many queues as cores on the underlying node(s).

Does RabbitMQ automatically create queues?

In RabbitMQ, a producer never sends a message directly to a queue. Instead, it uses an exchange as a routing mediator. Therefore, the exchange decides if the message goes to one queue, to multiple queues, or is simply discarded.

Does RabbitMQ use RPC?

In general doing RPC over RabbitMQ is easy. A client sends a request message and a server replies with a response message. In order to receive a response the client needs to send a 'callback' queue address with the request.

How do I set the queue in RabbitMQ?

Server-named Queues In AMQP 0-9-1, the broker can generate a unique queue name on behalf of an app. To use this feature, pass an empty string as the queue name argument: The same generated name may be obtained by subsequent methods in the same channel by using the empty string where a queue name is expected.


1 Answers

Let's just accept for a moment that it is not a horrible idea to implement RPC over message queues (like RabbitMQ)

it's not horrible at all! it's common, and recommended in many situations - not just legacy integration.

... ok, to your actual question now :)


from a very high level perspective, here is what you need to do.

Your request and response need to have two key pieces of information:

  • a correlation-id
  • a reply-to queue

These bits of information will allow you to correlate the original request and the response.

Before you send the request

have your requesting code create an exclusive queue for itself. This queue will be used to receive the replies.

create a new correlation id - typically a GUID or UUID to guarantee uniqueness.

When Sending The Request

Attach the correlation id that you generated, to the message properties. there is a correlationId property that you should use for this.

store the correlation id with the associated callback function (reply handler) for the request, somewhere inside of the code that is making the request. you will need to this when the reply comes in.

attach the name of the exclusive queue that you created, to the replyTo property of the message, as well.

with all this done, you can send the message across rabbitmq

when replying

the reply code needs to use both the correlationId and the replyTo fields from the original message. so be sure to grab those

the reply should be sent directly to the replyTo queue. don't use standard publishing through an exchange. instead, send the reply message directly to the queue using the "send to queue" feature of whatever library you're using, and send the response directly to the replyTo queue.

be sure to include the correlationId in the response, as well. this is the critical part to answer your question

when handling the reply

The code that made the original request will receive the message from the replyTo queue. it will then pull the correlationId out of the message properties.

use the correlation id to look up the callback method for the request... the code that handles the response. pass the message to this callback method, and you're pretty much done.

the implementation details

this works, from a high level perspective. when you get down into the code, the implementation details will vary depending on the language and driver / library you are using.

most of the good RabbitMQ libraries for any given language will have Request/Response built in to them. If yours doesn't, you might want to look for a different library. Unless you are writing a patterns based library on top of the AMQP protocol, you should look for a library that has common patterns implemented for you.

If you need more information on the Request/Reply pattern, including all of the details that I've provided here (and more), check out these resources:

  • My own RabbitMQ Patterns email course / ebook
  • RabbitMQ Tutorials
  • Enterprise Integration Patterns - be sure to buy the book for the complete description / implementation pattern. it's worth having this book

If you're working in Node.js, I recommend using the wascally library, which includes the Request/Reply feature you need. For Ruby, check out bunny. For Java or .NET, look at some of the many service bus implementations around. In .NET, I recommend NServiceBus or MassTransit.

like image 115
Derick Bailey Avatar answered Sep 19 '22 17:09

Derick Bailey