Before going ahead with this blog, we should understand the Queuing Systems, RabbitMQ. But if you don't have it, then it's not the end of the world, let me summarize the whole RabbitMQ and Queuing system by taking a simple example.
Treat RabbitMQ as a Post Office
Treat RabbitMQ as a Post Office.
Producers in real life are just the end-users who are sending their mails to the Post Office and here in Rabbitmq world they are processes that send the task to RabbitMQ
Exchange in real life is the postman that just routes the mail to specific postboxes and here in RabbitMQ exchanges are just routing the tasks to specific queues.
The task in real life is the mail that the postman sends to the postbox and in RabbitMQ world it's the technical information that sends to exchange.
Queue in real life is the Postbox that is having all the mails and here in RabbitMQ queue has all the tasks in it and they are processed in a first-in-first-out manner.
Now let’s directly jump into what exchanges are in RabbitMQ. In RabbitMQ, when the producer creates a message that will not directly be sent to a queue, instead first the message will be sent to exchanges, then after that, a routing agent reads it and sends it to the appropriate queue with help of header attributes, bindings, and routing keys.
RabbitMQ Exchange Types
In RabbitMQ, we have four types of Exchanges are available to route the message in different ways.
Following are the different types of exchanges available in RabbitMQ.
The routing in “Direct Exchange” is simple, a message goes to the queues whose binding key exactly matches the routing key of the message.
The direct exchange type is useful to distinguish messages published to the same exchange using a simple string identifier.
Let’s say we create a direct exchange ‘color’ in RabbitMQ Management Console
And two queues with routing key ‘orange’ and ‘blue’ respectively.
Now the exchange color will route the task to the orange queue that is having orange(exact match) as a routing key and it will route the task to the blue queue that is having a blue(exact match) as a routing key
If the routing key does not match any binding key, the message is discarded. If more than one queue is bound to exchange with the same binding key, the direct exchange will broadcast the message to all matching queues.
A fanout exchange routes a message to all queues that are bound to it regardless of the routing keys. The keys provided will simply be ignored.
Fanout exchanges can be useful when the same message would be consumed by two or more different queues. For example, when the user account is created, it should send a welcome email to the end-user and a text message to the end-user about the successful registration. This can be done using Fanout exchange that will send the message to two different queues is for Email and another one for SMS
Topic exchange is similar to direct exchange, but the routing is done according to the routing pattern and the wildcard. Instead of using a fixed routing key, it uses wildcards. Messages are routed to one or many queues based on a matching between a message routing key and pattern.
The routing key should be delimited by “.”. And the binding key will follow the same fashion however it can use the following wildcards as well
- * (star) can substitute for exactly one word.
- # (hash) can substitute for zero or more words.
Let’s say, we have two queues with binding key *.orange.*, *.*.rabbit and lazy.#
These findings can be summarised as:
- Q1 is interested in all the orange animals.
- Q2 wants to hear everything about rabbits, and everything about lazy animals.
Now the messages like below will go to Q1
- crazy.orange.rabbit(will go to Q2 as well)
- lazy.orange.elephant(will go to Q2 as well)
The messages like below will go to Q2
- crazy.orange.rabbit(will go to Q1 as well)
quickly.orange.male.rabbit will not go to any of the Queue.
A headers exchange is an exchange that routes messages to queues based on message header values instead of routing key. The producer adds some values in a form of key-value pair in the message header and sends it to the headers exchange. After receiving a message, the exchange tries to match all or any (based on the value of “x-match”) header value with the binding value of all the queues bound to it.
The producer can add one special value in the header of the message called “x-match“, The “x-match” can have two different values, “any” or “all“, where “all” is the default value. “all” means all the header key-value pairs must match while “any” means at least one of the headers key-value pairs must match with the binding value of the queue. The value in header key-value pairs can be of any data type like integer, string, or even hash.
Let’s say we have two queues with binding values as
(‘x-match’, ‘all’), (‘channel’, ‘google’), (‘first-time-logged-in’, ‘yes’)
(‘x-match’, ‘any’), (‘channel’, ‘email’), (‘phone-available’, ‘yes’)
Messages with headers like [(‘channel’, ‘email’)(‘phone-available’, ‘no’)] and [(‘phone-available’, ‘yes’)] will be routed to SMS Queue as the x-match property is any so any value that is matching the binding will be routed to SMS Queue. In the first case channel matched and in the other case phone-available matched.
Messages with headers like [(‘channel’, ‘google’)(‘first-time-logged-in’, ‘yes’), (‘phone-available’, ‘yes’)] [(‘channel’, ‘google’)(‘first-time-logged-in’, ‘yes’)] will route to EMAIL Queue as the x-match property is all so all the header values should match with the queue bindings.
Use the exchange according to your case. A direct/topic exchange can work as a fanout exchange if the binding key of all queues is the same. Using Exchanges extensively and appropriately can simplify/improve your Queuing architecture to a great extent.
I hope, it has helped you or it will help you. If you want to discuss anything or anything related to tech, you can contact me here or on my personal blog Progress Story.