Amazon MQでMQTTを使うために調査する

## はじめに
「MQ」や「MQTT」という言葉について全く知らなかったので、調査して理解できた内容をまとめています。
AWSでもAmazon MQとして使用されているようなので、更に理解を深めるためにAWSではどのように使用されているか調査しました。

## MQ
> メッセージキューイング（MQ）とは、異なるソフトウェア間でデータを送受信する手法の一つで、直接データを渡すのではなく一旦第三者のソフトウェアに預けることで、送信側も受信側も好きなタイミングで送受信処理をおこなうことができるようにする方式。
[IT用語辞典 e-Words](https://e-words.jp/w/%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%AD%E3%83%A5%E3%83%BC%E3%82%A4%E3%83%B3%E3%82%B0.html)

ここで出てくる「メッセージ」とは、メールやLineなどで送信するようなメッセージではなく、プログラム内のデータというイメージです。
本来、メッセージを送受信する際には、メッセージの送信と受信のタイミングを合わせる必要があります。
ですが、第三者のソフトウェア(ブローカー)を経由することで、メッセージを送る側と受け取る側どちらも好きなタイミングで実行できるようになります。
その結果、相手側のシステム状況を気にする必要がなくなるため、システムの独立性を上げることができます。

オープンソースの有名なミドルウェアとして、Apache ActiveMQやRabbitMQ、Apache Kafkaなどがあげられます。

## Amazon MQ

> Amazon MQ は、AWS でメッセージブローカーの設定や運用を簡単に行えるようにしてくれる、 Apache ActiveMQ および RabbitMQ 向けのマネージド型メッセージブローカーサービスです。
[Amazon MQ とは | AWS](https://aws.amazon.com/jp/amazon-mq/?amazon-mq.sort-by=item.additionalFields.postDateTime&amazon-mq.sort-order=desc)

MQをAWSで使用できるようにしたサービスです。
ブローカー用のEC2インスタンスを自動で管理してくれるイメージです。

## MQTT

> MQTTとは ”Message Queue Telemetry Transport” の略で、パブリッシュ/サブスクライブ型の非常にシンプルで軽量なメッセージングプロトコルです。制約のあるデバイスや、低帯域幅、高レーテンシー、または信頼性の低いネットワーク向けに設計されています。
[MQTT入門ガイド](https://www.advanet.co.jp/2020/10/14/mqtt-introduction/)

MQTTは通信プロトコルの一種で、TCP/IPネットワークで利用できます。
HTTPなどと比べてが軽量で、バッテリーの消費を抑えたい場合や、帯域幅が限られているネットワーク環境に利用されています。(主にIoT)
また、非同期でメッセージをやり取りできるのも特徴です。

## MQTTの構成
### Pub/Subメッセージングモデル
MQTTはpublish/subscribe型のメッセージングモデルが使用されています。
メッセージの送信側をpublisher（パブリッシャー）、メッセージの受信側をsubscriber（サブスクライバー）と呼び、MQTTサーバー(ブローカー)がメッセージを仲介します。
AWSでは、Amazon MQがブローカーに該当します。

### MQTTの仕組み
publisherとsubscriberは、「トピック」を通じてメッセージのやり取りを行います。
「トピック」というのは、メッセージを格納する箱のようなイメージです。
MQTTでは、トピックは「/」（スラッシュ）を使って階層構造になっています。
publisherとsubscriberが同じトピックを指定することで、該当するメッセージを受け取ることができます。

#### 送受信の流れ

①Subscriber1が`dev/test/num1`というトピックをサブスクライブします。
Subscriber2は`dev/test/num2`というトピックをサブスクライブします。

![mqtt_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683291/fbfb5338-9839-48d8-b04a-689a73d89651.png)


②Publisher1が`dev/test/num1`に"test"というメッセージを送信します。

![mqtt_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683291/5a8df1b2-bcf0-45dd-95df-745441377a1d.png)

③Subscriber1に"test"というメッセージが届きます。
Subcriber2はサブスクライブしているトピックが違うため、メッセージは届きません。

![mqtt_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683291/1ce7a720-0d95-4169-9ce5-86fd3c04f298.png)


基本的にブローカーではメッセージを保持しないため、パブリッシュされた直後にメッセージは消えてしまいます。
そのため、パブリッシュされた後にサブスクライブしてもメッセージを受け取ることができません。


#### トピックの指定方法
トピックは、`+`や`#`のワイルドカードを使用する事によって複数指定することが可能です。
 `+`は指定箇所のみ、`#`はそれ以下の階層すべてを複数指定できます。


**例**

「2024/01/01」 

上記のトピックには、2024年１月１日のデータが格納されているとします。

「2024/01/+」

とすると、１月中のトピックが全て指定できます。
また、

「2024/+/+」
「2024/#」

のようにすると、2024年のトピックはすべて選択できるようになります。
ただし、`#`を使用すると、それ以下の階層は強制的にすべて含まれてしまうため、`2024/#/01`のような使い方はできません。


## SNS、SQSとの使い分け
> 業界標準の API とプロトコルがサポートされているため、どのような標準に準拠したメッセージブローカーからでも、アプリケーション内のメッセージングコードを書き換えることなく Amazon MQ に切り替えられます。クラウド上でまったく新しいアプリケーションを構築される場合は、Amazon SQS と Amazon SNS のご検討をお勧めします。
[Amazon MQ に関するよくある質問](https://aws.amazon.com/jp/amazon-mq/faqs/)

AWSのサービスにSNSやSQSといったAmazon MQに似たメッセージ送信をするサービスがありますが、SNSやSQSはプロトコルなどの設定がAWS独自のものになっているため、既存のシステムをAWSのサービスに置き換える場合はメッセージングコードやプロトコルの設定を書き換える必要があります。
対してAmazon MQは、業界標準の API とプロトコルがサポートされていることによって、既存のシステムをAWSのサービスに置き換える場合でもメッセージングコードやプロトコルの設定は変更不要のため、MQTTなどのプロトコルを使用したい場合はAmazon MQを使うことになります。


## Amazon MQのエンジン選択
Amazon MQでは使用できるエンジンとしてActiveMQとRabbitMQをサポートしていますが、どちらを使用すれば良いか分からなかったため調査しました。

### どちらを使用すれば良いのか？
使用したいプラットフォームやプロトコルによってActiveMQかRabbitMQを使い分ける必要があるので、それぞれの状況によって使い分ける必要があります。

### ActiveMQ
ActiveMQはオープンソースのJavaベースのメッセージブローカーです。
複数の標準規格プロトコル（AMQP、STOMP、MQTT 等）をサポートしており、幅広い言語（Java、C、C++、Ruby、Perl、Python、PHP等）を選択することができます。
ActiveMQは、Subscriberの状態を考慮せずに送信するため、ブローカーにメッセージを溜め込みません。

### RabbitMQ
一方、RabbitMQ はJavaベースではなく、さまざまなプラットフォームや言語間でメッセージングを標準化することを目的としたメッセージブローカーです。
プロトコルはAdvanced Message Queuing Protocol (AMQP)をサポートしています。
RabbitMQはActiveMQと違い、Subscriberの状態を考慮するため、送信が失敗したりSubscriberがいなかった場合はブローカーにメッセージを溜め込みます。

## 最後に
MQやMOTTについて、基礎的な内容や仕組みについてまとめました。
次回は実際にAWS上でMQ環境を構築してテストしてみたいと思います。
Amazon MQでMQTTを使用する予定なので、エンジンはプロトコルがサポートされているActiveMQを使用したいと思います。