Add the rabbitmq module
This commit is contained in:
71
rabbitmq/docs/02-exchanges.md
Normal file
71
rabbitmq/docs/02-exchanges.md
Normal file
@@ -0,0 +1,71 @@
|
||||
[← The on-ramp](01-the-on-ramp.md) · [Module README](../README.md) · [The silent drop →](03-the-silent-drop.md)
|
||||
|
||||
# 2. Four exchange types
|
||||
|
||||
A producer never publishes to a queue. It publishes to an **exchange** with a **routing key**,
|
||||
and bindings decide where that lands. The whole topology is in
|
||||
[`Topology.java`](../src/main/java/com/ankurm/rabbit/Topology.java) as beans; `RabbitAdmin`
|
||||
declares them when the connection opens.
|
||||
|
||||
## Direct — exact match
|
||||
|
||||
Binding key `new` receives routing key `new`. Nothing else. This is the workhorse: one queue per
|
||||
command type.
|
||||
|
||||
## Fanout — routing key ignored entirely
|
||||
|
||||
Every bound queue gets a copy. `audit.all` and `analytics.all` both receive it, and the routing
|
||||
key you passed is not consulted at all. Use it for broadcast; use it knowing that adding a queue
|
||||
adds a full copy of the traffic.
|
||||
|
||||
## Topic — wildcards over dot-separated words
|
||||
|
||||
`*` is **exactly one word**. `#` is **zero or more**. The distinction is the one people get
|
||||
wrong, so here it is against a real broker
|
||||
([`docs/output/topic-wildcards.txt`](output/topic-wildcards.txt)):
|
||||
|
||||
```
|
||||
routing key orders.eu orders.high note
|
||||
order.eu.high true true matches both
|
||||
order.eu.low true false matches order.eu.* only
|
||||
order.us.high false true matches order.#.high only
|
||||
order.eu.west.high false true matches order.#.high only - * is one word
|
||||
order.high false true matches order.#.high - # can be zero words
|
||||
```
|
||||
|
||||
Bindings are `order.eu.*` and `order.#.high`. Two rows are worth pausing on:
|
||||
|
||||
- `order.eu.west.high` does **not** match `order.eu.*`, because `*` matches one word and `west.high`
|
||||
is two. Regex intuition says otherwise.
|
||||
- `order.high` **does** match `order.#.high`, because `#` matches zero words. So a binding you
|
||||
wrote to mean "something in the middle" also matches "nothing in the middle".
|
||||
|
||||
Design routing keys most-general-to-most-specific (`order.eu.west.high`, not
|
||||
`high.order.eu.west`), because `#` and `*` work left to right and a hierarchy you can bind
|
||||
usefully is one that starts broad.
|
||||
|
||||
## Headers — match a map, ignore the routing key
|
||||
|
||||
`x-match=all` requires every named header to be present **and equal**. `x-match=any` requires
|
||||
one. From `RoutingTest`:
|
||||
|
||||
| Message headers | `x-match=all` queue | `x-match=any` queue |
|
||||
|---|---|---|
|
||||
| `priority=high, region=eu` | yes | yes |
|
||||
| `priority=high` | no | yes |
|
||||
| `priority=high, region=us` | no | yes |
|
||||
|
||||
The third row is the one to remember: `all` matches on **value**, not on presence. A header that
|
||||
is there with the wrong value fails the same way a missing one does.
|
||||
|
||||
Headers exchanges are slower than topic exchanges and much less common. Reach for them when the
|
||||
routing criteria are genuinely multi-dimensional and do not compose into a hierarchy.
|
||||
|
||||
## The default exchange
|
||||
|
||||
Publishing to the empty exchange name `""` routes by **queue name**, using the routing key as the
|
||||
queue name. Every queue is implicitly bound to it. That is how
|
||||
`convertAndSend("", "orders.work", message)` works, and it is the one piece of AMQP that behaves
|
||||
like a magic constant.
|
||||
|
||||
[The silent drop →](03-the-silent-drop.md)
|
||||
Reference in New Issue
Block a user