RabbitMQ, some notes about the exchanges

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