MQTT入門ガイド

MQTT

MQTT入門ガイド

MQTTとは ”Message Queue Telemetry Transport” の略で、パブリッシュ/サブスクライブ型の非常にシンプルで軽量なメッセージングプロトコルです。制約のあるデバイスや、低帯域幅、高レーテンシー、または信頼性の低いネットワーク向けに設計されています。

その設計原理は、ネットワーク帯域幅とデバイスリソースを最小限に抑えつつ、メッセージ配信の一定の信頼性を確保する、というものです。

これらの原理は、M2M (Machine-to-Machine) や IoT (Internet of Things) といったデバイス同士が接続される世界においても、また帯域幅とバッテリー消費が鍵となるモバイルアプリケーションにとっても理想的なプロトコルであると言えます。

MQTTは1999年に、IBMのAndy Stanford-Clark博士と 、Arcom (現Eurotech)の Arlen Nipperによって開発されました。

この記事ではMQTT入門編として、MQTTがどのように機能し、なぜIoTに最適なのかを解説していきたいと思います。

HTTPは時代遅れ?

HTTPはパーソナルコンピューティング時代の相互(1対1)接続用として設計されました。一方、IoTのクライアントとサーバーは、センサアレイからコネクテッドカーなど物理オブジェクトが多岐にわたり(1対多または多対多)、コネクティビティがその生命線となります。

そうした物理デバイス網をサポートするためには、MQTTのようなIoTに適した接続プロトコルが必要です。

MQTTは軽量で、一度確立した接続を可能な限り再利用するパブリッシュ&サブスクライブ型のMachine-to-Machine通信プロトコルです。

MQTTプロトコルはブローカーと呼ばれる中継サーバーを利用し、接続のプロビジョニングを向上させるため、さまざまなクライアントデバイスがブローカーサーバーを通じてサービスへと接続するIoTにおいて、データ消費量を大幅に削減できます。MQTTではバイナリ2バイトのヘッダーを使用します。

MQTT vs HTTP 性能比較

MQTT はHTTPに比べて次のようなメリットがあります。(3G回線上での比較)

  • スループットが93倍UP
  • 送信時のバッテリー使用量が91.5%減
  • 受信時のバッテリー使用量が99.4%減
  • 接続保持電力が50%減
  • ネットワークオーバーヘッドが87.5%減
MQTT Table
http://stephendnicholas.com/archives/1217

IoTの課題

Webアプリケーションとは異なり、IoTプロジェクトにはいくつか特有の課題があります。主な課題の1つは、IoTがイベント駆動型プログラミングを必要とすることです。代表的なイベント駆動型プログラミングの機能は以下が挙げられます。

  • 1対多での情報発信
  • イベント発生時にイベント受信
  • 小データパケットの大量配信
  • 不安定なネットワーク上でのプッシュ通知

 

M2Mアプリケーションで直面する課題もあります。

  • 送信データの量(コスト)
  • 消費電力
  • 応答性
  • 不安定なコネクティビティでの確実な配信
  • セキュリティとプライバシー
  • スケーラビリティ

 

こうした課題に対して、MQTTはまさに最適なプロトコルと言えるでしょう。

MQTTのパブリッシャー/サブスクライバーモデル

MQTTは、パブリッシャー/サブスクライバー型のMachine-to-Machine通信のためのプロトコルです。

疎結合のため、パブリッシャーとサブスクライバーの結びつきは比較的緩い状態となっています。パブリッシャーはサブスクライバーにメッセージを送信しますが、実際にそこにサブスクライバーがいるかどうかは分かりません。そしてサブスクライバーも、パブリッシャー対する明確な知識がないままメッセージを受信します。トピックの情報を受け取るサブスクライバーがいない場合は、メッセージはドロップされます。

MQTT - Broker

Pub/Sub型のメッセージングパターンは次の3つで構成されています。

  1. パブリッシャー:ブローカーにメッセージを送信します。
  2. サブスクライバー:カテゴリー毎にメッセージをサブスクライブします。
  3. ブローカー:パブリッシャーからメッセージを受信し、サブスクライバーのサブスクリプションを維持します。

 

パブリッシャーは、パブリッシュされたメッセージをクラスに分類し、サブスクライバーはメッセージを受信します。基本的に、パブリッシャーに対してブローカーが1つあり、ブローカーが複数の出力チャネルに分割し、各サブスクライバーにメッセージを届けます。サブスクライバーは、1つまたはそれ以上のクラスをサブスクライブすることで、受け取りたいメッセージのみを受信できます。

Pub/Subのメリット

  1. 疎結合:パブリッシャーはサブスクライバーのアドレスやIDを認識せず、またメッセージタイプを意識せずに送信ができます。
  2. セキュリティの向上:ブローカーは、サブスクライブされたトピックのメッセージのみを送信します。
  3. テスト容易性の向上:トピックにより、テストに必要なメッセージの数が減ります。

MQTTの階層型名前空間

トピックとはMQTTクライアントが情報を共有するためのアドレス形式です。

トピックは、ファイルシステム内のフォルダやファイルのような階層構造になっていて、スラッシュ(/)を区切り文字としてしようします。

MQTTの階層構造のトピックは柔軟性をもたらします。例えば、SENSOR1TEMP、SENSOR1ALARM、SENSOR2TEMPなどのトピック名を付けると、システムに後付けでセンサを付加する場合、サブスクライブするアプリケーションも変更してトピックを受信する必要があります。

しかし、階層化されたトピックの名前空間では、アプリケーション設計者はトピックを整理し、管理を簡素化できます。SENSOR / 1 / TEMPのように「/」で区切ることによって、メッセージの送り先の指定や、メッセージを指定して受け取ることができるようになります。

トピック/サブスクリプション

MQTTのメッセージはトピック上へパブリッシュするだけで、トピックを設定する必要はありません。トピックはスラッシュ(/)を区切り文字として利用し、階層として扱われます。例えば、複数のセンサがそれぞれの情報をトピックへとパブリッシュした場合、それぞれの設置場所や機器名によって適宜メッセージは仕分けされます。

sensors/POSITION/temperature/MACHINE_NAME

クライアントは、サブスクリプションを作成することでメッセージを受信できます。サブスクリプションは、特定のトピックのメッセージのみを受信することができるほか、ワイルドカードを使うことも可能です。ワイルドカードとは「+」または「#」の記号を使い、複数の トピックを同時に指定できる機能です。

例えば「+」は、シングルレベルのワイルドカードとして使用します。上記のトピックをsensors/+/temperature/+のようなワイルドカードにした場合、すべてのPOSITIONと、すべてのMACHINE_NAMEの情報を受け取ることができます。

メッセージ保持

すべてのメッセージは保持されるように設定できます。これは、ブローカーがメッセージをすべてのサブスクライバーに送信した後でも保持されることを意味します。その後、保存されたメッセージのトピックに一致する新しいサブスクリプションが作成されると、メッセージがクライアントに送信されます。トピックがたまにしか更新されず、メッセージが保持されていない場合は、新しくサブスクライブしたクライアントは更新を受信するために長時間待たなければなりませんが、メッセージが保持されていればクライアントはすぐに受信できます。

クリーンセッション/ 永続的接続

接続において、クライアントはクリーンセッション(クリーンスタート)フラグを設定します。クリーンセッションがfalseに設定されている場合、接続は永続的となります。つまりクライアントが切断しても、クライアントが持っているサブスクリプションは残り、ふたたび接続するまで後続のQoS 1またはQoS 2メッセージは保存されます。クリーンセッションがtrueの場合は、クライアントが切断すると、クライアントのすべてのサブスクリプションが削除されます。

QoS (クオリティ・オブ・サービス)

各メッセージには、0〜2の整数で配信モードを指定することができます。これはQoS(クオリティ・オブ・サービス)と呼ばれており、次の 3つのタイプがあります。

0(Fire and forget)– 高速の配信方法で、メッセージは1回だけ配信されます。メッセージ受領の確認は行われません。

1(Acknowledgement)– メッセージは最低1回、エラー発生時には繰り返し配信されます。応答が確認されるまで配信は続けられます。

2(Synchronized)– メッセージは1回だけ配信されます。メッセージの配信は保証されますが、速度は最も遅くなります。

MQTTのセキュリティ

セキュリティは、しばしば堅牢さと利便性のトレードオフと言われます。このトレードオフはIoTではより興味深いものになります。
セキュリティにおけるチャレンジはフィールドに設置済みのデバイスをアップデートするときに発生します。特に不安定なネットワークで多くのIoTデバイスが稼働している場合には、すべてのデバイスを同時にアップデートするにあたりセキュリティの確保が非常に重要です。

この課題に正しく対処するには、IoT実装プロセスの初期段階から、アプリケーション開発者がセキュリティを最大のテーマとして考えておく必要があります。
MQTTのセキュリティは複数のレイヤーに分割されていて、各レイヤーは異なる種類の攻撃を防ぎます。
MQTTの役割は、IoTにおいて軽量で使いやすい通信プロトコルを提供することですので、プロトコル自体はいくつかのセキュリティメカニズムのみに特化していますが、MQTTの実装では、通常トランスポートセキュリティ用のSSL/TLSなど、他の最先端のセキュリティ標準を使用します。

ネットワークレベル

安全かつ信頼性の高い接続を実現する方法は、物理的に安全なネットワークにするか、クライアントとブローカー間のすべての通信にVPNを用いることです。このソリューションは、ゲートウェイが一方ではデバイスに接続され、もう一方ではVPNを介してブローカーに接続されるゲートウェイアプリケーションに適しています。

トランスポートレベル

機密性が優先されるべきケースでは、トランスポートを暗号化するSSL/TLSが広く使用されています。これは転送中にデータが読み取られないための安全な方法で実績もあり、クライアント証明書認証を発行することで双方のIDを検証します。

アプリケーションレベル

トランスポートレベルでは通信が暗号化されIDが認証されます。 MQTTプロトコルは、アプリケーションレベルでデバイスが認証されるように、クライアントIDとユーザー名/パスワードを提供します。これらのプロパティは、プロトコル自体によって提供されます。各デバイスが実行できるようにするための認証あるいは制御は、ブローカーの実装によって定義されます。

TLS/SSL

TLS (Transport Layer Security) と SSL (Secure Sockets Layer) は、クライアントとサーバー間を安全に通信するための暗号化プロトコルです。

MQTTはTCPトランスポートプロトコルをベースとしています。デフォルトでは、TCPの通信では暗号化はされません。よってMQTT通信全体を暗号化するために、多くのMQTTブローカーでは、プレーンTCPではなくTLSを使用します。

TLSの重要性

プレーンなTCP/IPを使用することは、葉書を送るようなもので、第三者がその内容を読むことができます。 TCPパケットは相手に到達する前にルーター、ファイアウォール、インターネット交換ポイントなどを通過しますが、その途中のいずれでもパケットの内容をクリアテキストで読み取るだけでなく、変更することもできてしまいます。

TLSは、安全な通信チャンネルを利用できるように特化された技術です。 TLSでは通信内容が第三者によって読み取られたり変更されたりすることはありません。

デジタルトランスフォーメーションにご興味のある方は当社のオリジナル記事もあわせてご覧ください!