MQTTは、メッセージキューイング/メッセージキューイングサービスのための軽量なパブリッシュ/サブスクライブ型のマシン間ネットワークプロトコルです。モノのインターネット(IoT)のように、リソース制約やネットワーク帯域幅が制限されたデバイスを持つ遠隔地との接続用に設計されています。順序付けされた、ロスレスの双方向接続を提供するトランスポートプロトコル(通常はTCP/IP)上で動作する必要があります。 [ 1 ]これはオープンなOASIS標準であり、ISO勧告(ISO/IEC 20922)です。
IBMのアンディ・スタンフォード=クラークと当時Arcom Control Systemsに勤務していたアーレン・ニッパーは、1999年にこのプロトコルの最初のバージョンを作成しました。 [ 5 ]これは、 SCADA産業制御システム内で石油パイプラインを監視するために使用されました。[ 6 ]当時、デバイスは衛星リンクを介して接続されていましたが、衛星リンクは非常に高価だったため、帯域幅効率が良く、軽量で、バッテリー電力の消費が少ないプロトコルを持つことが目標でした。[ 7 ]
歴史的に、「MQTT」の「MQ」は、IBM MQ(当時は「MQSeries」)製品ラインに由来し、「Message Queue」の略です。しかし、このプロトコルは、名前とは裏腹に、パブリッシュ/サブスクライブ型のメッセージングを提供します(キューはありません)。 [ 8 ] IBMが公開した仕様では、バージョン3.1として、このプロトコルは「MQ Telemetry Transport」と呼ばれていました。[ 9 ] [ 10 ] OASISがリリースした後のバージョンでは、技術委員会自体は「OASIS Message Queuing Telemetry Transport Technical Committee」という名前ですが、プロトコルは厳密に「MQTT」と呼ばれています。[ 3 ] 2013年以降、「MQTT」は何も略していません。[ 11 ] [ 8 ]
2013 年、IBM は、仕様への軽微な変更のみが受け入れられることを保証する憲章とともに MQTT v3.1 を OASIS 仕様団体に提出しました。[ 3 ] IBM から標準のメンテナンスを引き継いだ後、OASIS は 2014 年 10 月 29 日にバージョン 3.1.1 をリリースしました。[ 12 ] [ 13 ]いくつかの新機能を追加したMQTT バージョン 5へのより大幅なアップグレードが2019 年3 月 7 日にリリースされました。[ 14 ]
MQTT-SN(MQTT for Sensor Networks)は、TCP/IP以外のネットワーク上のバッテリー駆動組み込みデバイスを対象とした、メインプロトコルのバリエーションです。双方向転送を提供するネットワークであればどれでも使用できます[ 15 ](UDPやシリアルリンクなど)[ 16 ]が、元々はZigbeeが設計対象でした[ 15 ]。MQTT -SNネットワーク内および外部MQTTネットワークとの通信は、「MQTT-SNゲートウェイ」によって調整されます[ 15 ] 。
MQTTプロトコルは、メッセージブローカーと複数のクライアントという2種類のネットワークエンティティを定義しています。MQTTブローカーは、パブリッシングクライアントからメッセージを受信し、適切な宛先クライアントにメッセージをルーティングするサーバーです。[ 17 ] MQTTクライアントは、MQTTライブラリを実行し、ネットワーク経由でMQTTブローカーに接続するあらゆるデバイス(マイクロコントローラから本格的なサーバーまで)です。[ 18 ]
情報はトピックの階層構造で整理されています。パブリッシャーが配信する新しいデータ項目がある場合、そのデータを含む制御メッセージを接続先のブローカーに送信します。ブローカーは、そのトピックを購読しているクライアントに情報を配信します。パブリッシャーは購読者の数や所在地に関するデータを持つ必要はなく、購読者もパブリッシャーに関するデータを設定する必要はありません。
ブローカーが、現在サブスクライバーがいないトピックに関するメッセージを受信した場合、メッセージの発行者がそのメッセージを保持メッセージとして指定していない限り、ブローカーはそのメッセージを破棄します。保持メッセージとは、保持フラグが true に設定された通常の MQTT メッセージです。ブローカーは、最後に保持されたメッセージと、選択されたトピックに対応するサービス品質(QoS) を保存します。保持メッセージのトピックに一致するトピック パターンをサブスクライブした各クライアントは、サブスクライブ後すぐに保持メッセージを受信します。ブローカーは、トピックごとに 1 つの保持メッセージのみを保存します。[ 19 ]これにより、トピックの新規サブスクライバーは、発行者からの次の更新を待つことなく、最新の値を受け取ることができます。
パブリッシングクライアントが初めてブローカーに接続する際に、ブローカーがパブリッシングクライアントが予期せずブローカーから切断されたことを検出した場合に、購読者に送信するデフォルトメッセージを設定できます。
クライアントはブローカーとのみやり取りを行うが、システムには複数のブローカーサーバーが含まれており、それらのサーバーは現在の購読者のトピックに基づいてデータを交換する。
MQTTの制御メッセージは、最小でわずか2バイトのデータで構成できます。必要に応じて、制御メッセージは最大256メガバイトのデータを扱うことができます。クライアントとブローカーの接続/切断、データの公開、データの受信確認、クライアントとサーバー間の接続監視に使用される、14種類の定義済みメッセージタイプがあります。
MQTTはデータ伝送にTCPプロトコルを使用します。UDPやBluetoothなどの他のトランスポート上では、MQTT-SNという派生プロトコルが使用されます。
MQTTは接続認証情報を平文で送信するため、セキュリティや認証のための対策は含まれていません。TLSを使用して暗号化することで、転送される情報を傍受、改ざん、偽造から保護し、セキュリティを確保できます。
デフォルトの暗号化されていない MQTT ポートは 1883 です。暗号化されたポートは 8883 です。[ 20 ]
MQTTブローカーは、コンピュータ上で動作するソフトウェアであり(オンプレミス環境またはクラウド環境)、自社開発することも、第三者にホストしてもらうことも可能です。オープンソース版とプロプライエタリ版の両方が提供されています。
ブローカーは郵便局のような役割を果たします。MQTTクライアントは、宛先の直接接続アドレスを使用するのではなく、「トピック」という件名を使用します。購読者は誰でも、そのトピックに関するすべてのメッセージのコピーを受け取ります。複数のクライアントが単一のブローカーからトピックを購読でき(1対多)、また、単一のクライアントが複数のブローカーのトピックを購読することもできます(多対1)。
各クライアントは、パブリッシュとサブスクライブの両方によってデータを生成および受信できます。つまり、デバイスはセンサーデータをパブリッシュしながら、構成情報や制御コマンドを受信できます(MQTTは双方向通信プロトコルです)。これにより、データの共有、デバイスの管理、および制御が容易になります。クライアントは同じデータを複数のトピックにブロードキャストすることはできず、それぞれに単一のトピックを指定して、複数のメッセージをブローカーにパブリッシュする必要があります。
MQTTブローカーアーキテクチャでは、クライアントデバイスとサーバーアプリケーションが分離されます。これにより、クライアントは互いの情報を知ることがなくなります。MQTTは、設定によっては、証明書、ユーザー名、パスワードで保護された接続でTLS暗号化を使用できます。オプションとして、接続には証明書が必要となる場合があり、その証明書はクライアントが提供するもので、サーバーのコピーと一致している必要があります。
障害発生時には、ブローカーソフトウェアとクライアントは自動的に冗長構成の自動バックアップブローカーに切り替えます。バックアップブローカーは、オンプレミス、クラウド、またはこれらの組み合わせなど、複数のサーバー間でクライアントの負荷を分散するように設定することも可能です。
ブローカーは、標準の MQTT と Sparkplug などの準拠仕様の MQTT の両方をサポートできます。[ 21 ]これは、同じサーバーで、同時に、同じレベルのセキュリティで実行できます。
ブローカーは、デバイスのオン/オフに関わらず、セッションのすべての情報を追跡します。これは「永続セッション」と呼ばれる機能です。この状態では、ブローカーは各クライアントの接続情報、各クライアントが購読しているトピック、およびQoSが1または2のトピックに関するメッセージを保存します。[ 22 ]
MQTTブローカーの主な利点は以下のとおりです。

サーバーとの接続が確立されるのを待ち、ノード間にリンクを作成します。
MQTTクライアントが実行すべき処理を完了し、TCP/IPセッションが切断されるまで待機します。
MQTTクライアントにリクエストを渡した後、すぐにアプリケーションスレッドに戻ります。
2019年にOASISは公式のMQTT 5.0標準をリリースしました。[ 1 ]バージョン5.0には、次の主要な新機能が含まれています。[ 23 ]
ブローカーへの各接続はQoS尺度を指定できます。[ 24 ]これらはオーバーヘッドの昇順に分類されます。
このフィールドは、基盤となるTCPデータ送信の処理には影響しません。MQTTの送信者と受信者の間でのみ使用されます。
MQTTプロトコルバージョン3.1.1では、サーバー(ブローカー)がクライアントによって指定されたキープアライブ値の1.5倍のタイムアウトを使用することが求められます。この仕組み(およびHTTPなどの他のプロトコルにおける同様のキープアライブ機能)により、 2020年に公開されたSlowITeと呼ばれる低速DoS攻撃が可能になります。この攻撃では、攻撃者は可能な限り多くの接続を開いて維持しようとし、正当なユーザーの接続を奪います。[ 25 ] [ 26 ]この攻撃の新しいバリエーションと新しい検出/軽減方法は、現在の研究テーマとなっています。
MQTTクラスタリングは、MQTTデプロイメントにおける高可用性、耐障害性、拡張性を確保するために用いられる技術です。[ 27 ]効率的で軽量なメッセージングプロトコルであるMQTTクラスタリングは、相互接続されたブローカーノードの回復力のあるネットワークの構築を可能にし、ハードウェア障害やネットワーク障害が発生した場合でも、継続的かつ信頼性の高いメッセージ配信を保証します。
MQTTは、独立したクライアントによって発行されたメッセージが、生成された順序で購読者に届くことを保証しません。OASIS MQTT仕様は、単一のトピック上の単一のクライアントセッション内でのみ順序保証を提供します。別のクライアントから発生したイベント、または独立した接続を介して生成されたイベントは、順不同で配信される可能性があります。[ 28 ]
この制限は、デバイスの接続状態を追跡するために MQTT ライフサイクル イベント (接続および切断通知) を使用するIoT展開において特に重大な影響を及ぼします。主要なブローカー実装では、この点を直接的に認めています。Amazon Web Services は、AWS IoT Core開発者向けドキュメントで、「ライフサイクル メッセージは順不同で送信される可能性がある」こと、およびサブスクライバーが「重複したメッセージを受信する可能性がある」ことを述べています。[ 29 ]同様に、HiveMQのエンジニアリング ドキュメントでは、「パブリッシング クライアント間で厳密な順序付けを行うには、専用のルーティングやシーケンス番号などの追加の戦略が必要となる」と指摘しています。[ 30 ]
実際的な結果として、再接続通知より前に生成された切断通知が、サブスクライブしているアプリケーションに後から到着する可能性があり、最終書き込み優先ポリシーを適用する監視システムが、デバイスが既に再接続しているにもかかわらず、オフラインとして記録してしまうことがあります。これはイベント駆動型アーキテクチャでよく知られている障害モードであり、分散システムに関する文献では、1978年にレスリー・ランポートによって非同期メッセージパッシングの固有の特性として特徴付けられました。 [ 31 ]独立したベンチマークでは、本番IoT展開におけるイベント順序の逆転による運用コストが文書化されています。[ 32 ]
一般的に適用される緩和策には、デバウンスウィンドウ(切断イベントに対するアクションを一定時間遅延させて、遅れて到着したメッセージを処理できるようにする)、ポーリングまたは再クエリパターン、およびアプリケーション層のシーケンス番号付けなどがあります。それぞれの緩和策にはトレードオフがあります。デバウンスウィンドウは、真の切断イベントの検出遅延を引き起こし、正当な通知を抑制する可能性があります。ポーリングはネットワークオーバーヘッドを増加させ、パッシブセンサーには適していません。[ 33 ]