RabbitMQ チュートリアルの要点まとめ

RabbitMQ を使うにあたっての要点を図解しつつまとめた記事です。主に[RabbitMQチュートリアル](https://www.rabbitmq.com/getstarted.html)の情報のまとめですが、チュートリアル外で得た情報も参照しつつ説明します。

# RabbitMQ とは？

チュートリアルの冒頭で RabbitMQ はメッセージブローカだと書かれています。つまり仲介者。

RabbitMQ は「メッセージ・キューイング」を実現するソフトウェアです。「メッセージ・キューイング」とはざっくりというと、アプリケーション間のデータのやり取りをする際に直接やり取りするのではなく、間にキューをはさみ、送信側がキューに溜め込んでいく方式のこと。こうすることで、例えば次に上げるようなメリットを得られるようになります。

* 送信側は、受信側の処理の終了を待つ必要がなく次の処理を続行できる
* 送信側と受信側に分離されるため、疎結合なデザインになりやすい
* 各アプリケーションをステートレスにしやすくスケールアウトしやすくなる

# 4つの登場人物を図解する。

RabbitMQ の概要を理解するにあたっては、Producer、Exchange、Queue、Consumer という 4 つの登場人物をおさえる必要があります。図解すると以下の通り。

![2018-04-29 22.15.47 からのスクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/48133/54c359ef-9e86-b43e-c2cd-0b8a9514019c.png)

# 各登場人物を理解する。

ここから、各登場人物について細かく見ていきます。

### Producer

メッセージを送信するプログラムのことです。送信する際に指定するのは次の 3 つです。

* メッセージ送付先の Exchange 名
* routing key
* メッセージ

直接キューにメッセージを送信するのではなく、Exchange 名を指定して Exchange 宛に送信します。受信側のことを考える必要はないので、疎結合化に一役買っているといえます。

### Consumer

メッセージを受信するプログラムのことです。受信の際に必要なのは、どの Queue からメッセージを受信するかだけ。送信側がどのようにメッセージを送信しているかを考える必要はありません。

### Exchange

どのメッセージをどのように配送するかのひも付けをするのが Exchange と Queue です。

Exchange で設定するのは自身の Exchange 名と、Exchange Type。Exchange Type によって、メッセージをどのように配送するかを設定でき、例えば以下のタイプがあります。

* fanout (exchange と紐付いた全てのキューにメッセージをブロードキャストする)
* direct　(ルーティングキーがバインディングキーとマッチするときのみ配送する)
* topic (ルーティングキーを fast.orange.rabbit のように「.」区切りで指定する。ルーティングキーがバインディングキーのパターンとマッチするときのみ配送する)
* 無指定 (この場合は、ルーティングキーで指定したキューに配送する)

### Queue

その名の通り、キューの役割。キューを作成する際に必要となるのが、次の二つの情報。言い換えるとキューが受け取りたいデータを設定します。

* どの Exchange と紐付けるか
* binding key

メッセージのルーティングキーを参照し、バインディングキーとマッチするものをキューにためていきます。


# ExchangeType

Exchange Type は上述したとおりいくつか種類がありますが「fanout」「direct」「topic」について、それぞれどのような動作をするか説明します。

※ なお、各チュートリアルのリンク先は Python にしていますが、他の多くの言語にも対応しています。

## fanout

Publish/Subscribe を実現するためのもの。[チュートリアル 3章 Publish/Subscribe](https://www.rabbitmq.com/tutorials/tutorial-three-python.html)で取り上げられているものです。

次の図のように Exchange と紐付いた全てのキューにメッセージを配送します。

![2018-04-29 22.22.27 からのスクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/48133/7c073d3e-b937-3340-d9a2-6d3546ec3706.png)

## direct

[チュートリアル 4章 Routing](https://www.rabbitmq.com/tutorials/tutorial-four-python.html)で取り上げられているものです。章の題名は Routing になっていますが、メッセージの種別に応じて、適切な相手に送り届けたい場合に使うのが Exchange Type の「direct」です。

次の図はログの深刻度(error, warning, info のいずれか)に応じて配送先を変える例になります。

![2018-04-29 22.28.16 からのスクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/48133/8b8f65ca-cbd3-392c-71ca-78a71a0273bc.png)

受信側はまずキューを作ります。その際、バインディングキーで受け取りたいメッセージの深刻度を指定します。バインディングキーは二つ以上の項目を設定できるので、error, warning, info の三つを指定することも可能です。

送信側はメッセージを送信する際、深刻度をルーティングキーで指定します。そうすることで、バインディングキーにマッチしたキューにのみ配送されるようになります。

## topic

[チュートリアル 5章 Topics](https://www.rabbitmq.com/tutorials/tutorial-five-python.html)で取り上げられているものです。

Exchange Type が Topics の場合は、ルーティングキーを fast.orange.rabbit のように「.」区切りで指定します。ルーティングキーがバインディングキーのパターンとマッチするときのみ配送するパターンです。

![2018-04-29 22.53.56 からのスクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/48133/27813964-a415-2285-c032-d20649e47a0d.png)



バインディングキーの設定にあたっては、二つの特殊な記号を使えます。

* (*) は 1 ワード
* (#) はゼロ個、もしくは複数個のワード

例えば、バインディングキーが「#.rabbit」の場合は、「fast.orange.rabbit」「black.rabbit」「rabbit」いずれの場合も受け取ることができます。
バインディングキーが「fast.*.rabbit」の場合は、「fast.orange.rabbit」は該当するので受け取ります。一方で「fast.rabbit」のようなメッセージは受け取りません。


# メッセージキューイングの他の選択肢は？

ここまで RabbitMQ の説明をしてきましたが、メッセージキューイングは RabbitMQ 以外にも様々な実装、サービスがあります。選定にあたって、有用なスライドがありました。

[Slideshare:ストリーム処理を支えるキューイングシステムの選び方](https://www.slideshare.net/laclefyoshi/ss-67658888)

観点としては、スループット、レイテンシであったり、やりたいことができるかどうかによると思います。
また、主要なクラウドサービスではフルマネージドのメッセージキューイングサービスが提供されています。コストとの兼ね合いになるかと思いますが管理はフルマネージドのサービスの方が楽だと思います。


# 参考

[Slideshare:ストリーム処理を支えるキューイングシステムの選び方](https://www.slideshare.net/laclefyoshi/ss-67658888)

[GREE Engineer's Blog:AMQPによるメッセージング](http://labs.gree.jp/blog/2010/06/262/)

[CyberAgent:Developers Blog:Apache Kafka & Google Cloud Pub/Sub 主要機能の比較](https://developers.cyberagent.co.jp/blog/archives/1672/)