RabbitMQ differs from brokers such as ActiveMQ because it uses a level of indirection between the producer and a consumer. The exchanges implement such indirection similarly (but not quite the same!) to how post offices are in the middle between who sends a postcard and who receives it.
The producer sends a message to an exchange specifying a routing key. The exchange finds all the queues listening to that particular routing key and propagates a copy of the message.
There are four types of exchanges: Direct
, Topic
, Fanout
, and Header
.
Direct
matches the routing key exctly. If a message has routing key foo.bar
, only the queues listening to foo.bar
will receive the message.
Topic
matches the routing key and allows wildcards. If a message has routing key foo.bar
, the queues listening to foo.bar
, to foo.*
, and to *.bar
will receive the message.
Fanout
is the simplest: it broadcasts all the messages to all the queues ignoring the routing key.
Header
works like Topic
, but using headers.
Recommendation
The recommendation is to use only Topic
(the most flexible) or Direct
(slightly faster) and to have only one exchange. Having multiple exchanges may be useful for the design, but it has costs in terms of performances.
Examples
Scenario: 1 producer, 2 consumers
With Direct Exchange
the producer and the consumers use my.routing.value
- both consumers receive all the messages
the producer uses my.routing.value
, one consumer uses my.*.value
, and the second consumer uses my.routing.value
- only the second consumer (with my.routing.value) receives a message
one consumer uses both my.routing.value1
and my.routing.value2
, the other consumer uses both my.routing.value1
and my.routing.value3
- when the producer uses
my.routing.value1
both consumers get the messages - when the producer uses
my.routing.value2
only one consumers gets the messages
With Topic Exchange
the producer and the consumers use my.routing.value
- both consumers receive all the messages
the producer and one consumer use my.routing.value
, and the second consumer uses my.*.value
- both consumers receive all the messages
the producer uses my.something.value
, one consumer uses my.routing.value
, and the second consumer uses my.*.value
- only the second consumer (with
my.*.value
) gets the message
the producer uses my.*.value
, one consumer uses my.foo.value
, and the second consumer uses my.bar.value
- no consumer receive anything
Final note
It is possible to bind the same queue to two different exchanges / routing keys
eg.
exchange-1
-routing-key1
exchange-2
-routing-key2
a queue can bind on both and receive all the messages