RabbitMQ Exchangeについて - 発展編 -

さて、今回は、Exchangeについてより詳しく見て行く事にします。

Exchangeはメッセージを受け取る役割を果たすコンポネントですが、
下記の種類があります。

Direct Exchange

メッセージをルーティングキーでキューにバインディングします。
ルーティングキーにワイルドカードは使えず、完全一致でメッセージのルーティングを行います。

同じルーティングキーで複数のキューにルーティングすることも可能です。
(その場合、fanoutと同じ挙動になる)

例)usa.weather.news というルーティングキーを持ったメッセージをupdateキューにバインディングする。


Fanout Exchange

エクスチェンジにバインドされたすべてのキューにメッセージをルーティング
ルーティングキーは無視されます。

複数のキューに同じメッセージをブロードキャストしたい場合に利用します。

例)EX1 に届いたメッセージは、すべてQ1,Q2,Q3に同様に配送する。メッセージに設定された、ルーティングキーなどは考慮されません。


Topic Exchange

ルーティングキーを使ってDirect Exchangeよりも細かいバインディング設定が可能です。

usa.news, usa.weather, usa.#
のようななルーティングキーを設定し、キューに対して
配送ルールを設定することが可能です。

ルーティングサンプルです。

[publisher A]
usa.news.weather のルーティングキーでメッセージを送信...(A)
[publisher B]
usa.news.business のルーティングキーでメッセージを送信...(B)


[consumer]
usa.# のルーティングキーでメッセージを取得するバインディングを行った場合(A)、(B)のメッセージとも取得することができます。
一方で、usa.news.weatherのルーティングキーでキューに対してバインディングを行った場合、(A)のメッセージのみ取得します。


※ルーティングキーでバインディングするため、特定のQueueをせずに
ルーティングキーの指定のみでッセージを送信することも可能です。

そのためTopic Exchangeを使う場合は、channel.queueDeclare() メソッドを利用して、
動的にキューを作成し、そこにメッセージをパブリッシュしてもよいです。

例えば下記のような一時キューが作成されます。
amq.gen-U0srCoW8TsaXjNh73pnVAw==.


その際、一時的なキューは、コンスーマが切断された際に削除されるよう、第三引数のexclusive=trueとするとよいです。
val queueName = channel.queueDeclare("", true, true, false, null).getQueue();

ルーティングキューに合わせたConsumerを作成してキューを監視していればOKですが、一時キューを利用するため、
コンスーマが落ちてしまうと、メッセージが失われてしまうので、オススメはしません。

本番では、ちゃんとdurableなExchangeやQueueを用意して運用した方が良いと思います。

まあでもTopic Exchangeが一番柔軟で、使いやすいのかもしれません。

Header Exchange

任意のヘッダの値を比較することで、ExchangeとQueueの間のバインディング
行います。
ルーティングキーは無視されます。
キューを宣言する際に、x-match値をargumentに設定します。
バインディングを行う際に、任意のヘッダを作成し、
そのヘッダにマッチするヘッダをメッセージが持っていれば、
キューにルーティングされます。

1. キューを宣言→ x-match:all or any をセット

- all の場合、すべてのargument条件にマッチしていれば、宣言したキューにルーティング
- any の場合、どれかのargument条件にマッチしていれば、宣言したキューにルーティング

2. Echange と1で宣言したキューとのbindingを作成

- binding作成時にargumentでルーティングするargumentを指定
- 例)hoge:test1, foo:test2 の二つを設定するとする。
- メッセージを送る。 そのメッセージのargument にhoge:test1 だけ指定してあった 場合、1でanyの場合はルーティングされるが、allの場合はルーティングされない。1でallが設定された場合は、hoge:test1, foo:test2両方が指定されないと、宣言されたキューにルーティングされない。

ルーティングキーではなく、メッセージヘッダの値によってバインディングを行うためのEchangeです。
メッセージの属性をヘッダー使って送る場合、それに合わせてルーティングを変えたいといった場合に有効です。



topic exchangeにしておけばたいていのルーティングには対応できます。
シンプルな構成だと、Direct Echangeでも大丈夫でしょう。
それよりも、メッセージの可用性を担保するように設計する方が重要だと思います。

この辺の絵が理解に役立つと思います。
https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_MRG/1.3/html/Messaging_User_Guide/chap-Messaging_User_Guide-Exchanges.html#sect-Messaging_User_Guide-Exchange_Types-Topic_Exchange


Exchangeについては以上です。

次は。。。クラスタリングとか、可用性を高める方法について超訳していきます!

チャオ!