In this article, we will learn the differences between RabbitMQ Topic vs Direct exchange. To learn more about other RabbitMQ topics, refer to these articles.
2. RabbitMQ Topic vs Direct Exchange
|A direct exchange delivers messages to queues based on the message routing key.||Topic exchanges route messages to one or many queues based on matching between a message routing key and the pattern that was |
used to bind a queue to an exchange.
|Can’t behave like other exchanges||Can behave like other exchanges|
|Does not support # or * wildcard characters||Supports special characters “*” and “#”|
|Can’t behave like a topic exchange||When special characters “*” (star) and “#” (hash) aren’t used in bindings, the topic exchange will behave just like a direct one.|
|You can bind multiple queues with the same binding key. |
In that case, the direct exchange will behave like fanout and will broadcast the message to all the matching queues.
|When a queue is bound with “#” (hash) binding key – it will receive all the messages, regardless of the routing key – like in fanout exchange.|
|It can’t do routing based on multiple criteria.||It can route based on multiple criteria|
See this article to understand the terminologies Queue, Exchange, Routing and binding keys.
3. RabbitMQ Direct exchange
A direct exchange is ideal for the Unicast routing (one-to-one) of messages (although we can use it for multi cast – one-to-many routing as well).
Here is how it works:
- A queue binds to the exchange with a routing key K
- When a new message with routing key R arrives at the direct exchange, the exchange routes it to the queue if K = R
3.1. Work queues
We can use the Work Queue to distribute time-consuming tasks among multiple workers or consumers.
In this way, you can avoid doing a resource-intensive task immediately and having to wait for it to complete. Instead, we schedule the task to be done later. We encapsulate a task as a message and send it to a queue. A worker process running in the background will pop the tasks and eventually execute the job.
This concept is especially useful in web applications, where it’s impossible to handle a complex task during a short HTTP request window.
The RabbitMQ can share the tasks with multiple workers.
3.1.1. Direct exchange with work queues
Direct exchanges are often used to distribute tasks between multiple workers or consumers (instances of the same application) in a round-robin manner.
It load balance the messages between consumers and not between queues.
The RabbitMQ will send each message to the next consumer, in sequence. On average, every consumer will get the same number of messages. This way of distributing messages is called round-robin.
Look at the following block. We have two workers listening for messages. RabbitMQ delivers each message sequentially. Worker 1 gets the first message and then worker 2 gets the second message. Again, worker 1 gets the third message and worker 2 gets the fourth message. The same process repeats.
// worker 1 java -cp $CP Worker # => [*] Waiting for messages. To exit press CTRL+C # => [x] Received 'First message.' # => [x] Received 'Third message...' # => [x] Received 'Fifth message.....' // worker 2 java -cp $CP Worker # => [*] Waiting for messages. To exit press CTRL+C # => [x] Received 'Second message..' # => [x] Received 'Fourth message....'
4. RabbitMQ Topic exchange
Topic exchanges route messages to one or many queues based on matching between a message routing key and the pattern that was used to bind a queue to an exchange.
The topic exchange type is often used to implement various publish/subscribe pattern variations. We widely used it for the multicast routing of messages.
Topic exchanges have a very broad set of use cases. Whenever a problem involves multiple consumers/applications that selectively choose which type of messages they want to receive, then we must consider using the topic exchanges.
Messages sent to a topic exchange can’t have an arbitrary
routing_key – it must be a list of words, delimited by dots. The words can be anything, but usually they specify some features connected to the message. A few valid routing key examples:
"quick.orange.rabbit". There can be as many words in the routing key as you like, up to the limit of 255 bytes.
4.1. Topic exchange binding key
The binding key must also be in the same form. The logic behind the topic exchange is similar to a direct one – a message sent with a particular routing key will be delivered to all the queues that are bound with a matching binding key.
However, there are two important special cases for binding keys:
- * (star) can substitute for exactly one word.
- # (hash) can substitute for zero or more words.
We created three bindings:
- Q1 is bound with a binding key
"*.orange.*"(interested in all the orange animals)
- Q2 with
"lazy.#". (interested in rabbit and lazy animals)
We will send the messages with a routing key that comprises three words (two dots). The first word in the routing key will describe a celerity, second a colour and third a species: “<celerity>.<colour>.<species>”.
A message with a routing key set to
"lazy.orange.elephant" go to both the queues.
"quick.orange.fox" will only go to the first queue, and
"lazy.brown.fox" only to the second.
"lazy.pink.rabbit" will be delivered to the second queue only once, even though it matches two bindings.
"quick.brown.fox" doesn’t match any binding, so it will be discarded.
To sum up, we have learned the differences between RabbitMQ Topic vs direct exchange mechanisms. You can find code samples in our GitHub repository.