IoTとMQTTとMODE
どーも、MODEでソフトウェアエンジニアをやっている@banana-umaiです。
今日はIoTな開発をしようとした際に必ずといってよいほど出てくるMQTTというプロトコルとMODEの提供するIoTプラットフォームの関係について書いてみたいと思います。
TL;DR
MQTTはマシンリソース・ネットワークリソースに乏しい環境での動作を前提として設計された双方向の軽量なバイナリメッセージングプロトコルです。
MQTT Brokerを利用することで気軽にMQTTを使ったシステムを開発することは可能ですが、本番運用に耐えうる堅牢なシステムを構築するのは簡単ではありません。
MODEの提供するIoTプラットフォームはMQTTによるIoTデバイスとの接続方式をサポートするものの、MQTT Brokerを提供していません。
MODEではアプリケーションサーバーがMQTT通信レイヤーを持ち、アプリケーション固有の振る舞いをすることで、信頼性のあるIoTシステムの構築を容易にしています。
MQTTとは?
MQTT(Message Queuing Telemetry Transport)の特徴を http://mqtt.org/faq の概要説明から抜粋すると
リソースが限定されるデバイスや劣悪なネットワーク環境(低帯域・高レイテンシ・低信頼性)での動作するようにデザイン。
極めてシンプルかつ軽量なメッセージングプロトコルで、Publish/Subscribeの双方向を想定。
というような特徴があげられます。
IoTにおいてIoTデバイスやゲートウェイなどのエッジマシンやその動作環境はまさに上記のような状況が多く、そのため、MQTTがIoT製品や多くのIoTプラットフォームで、クラウド <=> エッジ感の通信プロトコルとして多く用いられています。
デバイスから見た際に登り(Publish)と下り(Subscribe)の双方向の通信が可能なセッションを作成し、その上でバイナリフォーマットのメッセージのやりとりを行うことになります。最小のパケットサイズは2バイト(pingパケット)であり、ヘッダーサイズが小さい点、通信フットプリントはHTTPに比べると基本的には小さくしやすいという特徴があります。
MQTT同様にバイナリな双方向通信を行うWebSocketと比べた場合、MQTTはメッセージングプロトコルでもあるので、メッセージングに関する仕様が色々定義されています。一番わかり易い点としては・・・
トピックと呼ばれるメッセージのルーティングのための仕組みがある。
QoS(Quality of Service)というメタデータをメッセージのPublish/Subscribeの際に用いることでメッセージの配信に関しての精度をコントロールできる。
等の特徴が挙げられます。
MQTTを用いたシステム開発を行うといった場合、MQTT Brokerと呼ばれるサーバーソフトウェアを用いるのが典型的な。MQTT Brokerはその名の通り、IoTデバイスとアプリケーションサーバー郡の間でメッセージを仲介する役割を担います。
代表的なオープンソースソフトウェアとしては、Eclipse Mosquittoがあります。Mosquitoを使うと簡単にメッセージのPublishとSubscribeを試すことが可能です。
Mosquitto Serverを起動する。
$ docker run -it -p 1883:1883 -p 9001:9001
/foo トピックのメッセージをQoS 1で待ち受ける。
$ mosquitto_sub -t '/foo' -q 1
/foo トピックにメッセージをQoS 1で送信する。
$ mosquitto_pub -t '/foo' -m "hello" -q 1
アプリケーションのインストールとサーバーの起動がうまくいっていれば、mosquitto_subコマンドを起動しているshellの標準出力に"hello"と表示されるはずです。
(ツールのインストールに関してはMosquitto ServerのインストールやMosquitto Clientのインストールを参考にして下さい)
本稿では、これ以上MQTT自体に深入りはしませんが、MQTTに関してより深く知りたい方は、以下のドキュメント等で補足して頂くことをおすすめします。
MODEプラットフォームとMQTT
MODEプラットフォームとIoTデバイス間での通信はMQTTを利用しています。ですが、MODEプラットフォーム自体はMQTT Brokerではありません。MODEプラットフォームでは、IoTデバイスがMODEプラットフォームの機能を利用するためのプロトコルとしてMQTTを用いています。
ざっくりと言うとMODEプラットフォームの利用方法は以下のようになります。
MODEプラットフォームとIoTデバイスの間の通信のみでMQTTを用います。IoTデバイスからMODEプラットフォームに対してデータを送信にMQTT Publishを、逆に、MODEプラットフォームからIoTデバイスに対して命令やデータを送信する際にはMQTT Subscribeを利用しています。
一方、MODEプラットフォームとカスタマーのサーバーアプリケーションやスマートフォンアプリケーションの通信はREST APIやWebSocket等のより一般的なWEB技術を用います。MODEプラットフォームを経由してIoTデバイスにデータやコマンドを送信する場合には、MODEプラットフォームのREST APIを利用します。WebSocketを用いて、MODEプラットフォームからのIoTデバイスのデータを継続取得することも可能です。
MODEプラットフォームのアプリケーションサーバーはMQTTプロトコルでIoTデバイスからの接続を受付け、IoTデバイスがPublish/Subscribeするトピックに応じて、所与の動作を行います。
IoTデバイスがPublish可能なトピックとして「Event」トピックと「BulkData」トピックという2種類の代表的なトピックがあります。詳細は省きますが、リアルタイムに処理したい軽量なデータについてはEventトピックに対してデータを送信する、比較的データ容量が大きかったり、リアルタイムで処理必要はないがデータロストを防ぎたいような場合にはBulkDataトピックにデータを投げる、といった形で使い分けることができます。
一方、IoTデバイスがSubscribe可能なトピックとしては「Command」トピックと「KeyValue」トピックという2種類のトピックがあります。ユーザーアプリケーションはMODEプラットフォームのそれぞれのトピックに対応したREST APIを通じてIoTデバイスに対して命令やデータを送信できます。こちらも詳細は省きますが、Commandトピックはその名の通りデバイスに実行させたい「命令」を送信するために用います。一方、「KeyValue」トピックはデバイスとMODEプラットフォーム間でキーバリューストアを共有・同期するために用います。
アプリケーションサーバーがMQTTプロトコルを実装する価値
前項に書いた通り、MODEプラットフォームではMQTTを利用していますが、MQTT Brokerを利用するのではなく、アプリケーションサーバーがMQTTプロトコルを使ってIoTデバイスと通信します。そして、特定のMQTTトピックに対して、特定の機能(役割)を持っています(REST APIがリソースごとに機能があるのと同様)。
現状、Subscribe/Publish可能なトピックはそれぞれ2種類しかないので、一見すると、MQTTブローカーのような自由度がないように見えるかと思います。では、このようなアプローチのメリットはあるのでしょうか。
例えば、MQTT Brokerを利用した場合、以下のようなケースが存在します。
IoTデバイスからMQTT Brokerへのデータ送信が成功するものの、そこからApp Serverへのデータ通知(Subscribeを通じて同一トピックのメッセージをApp Serverが受信する)がサーバーやネットワークの不具合等の理由により失敗する、という可能性があります。
( QoSはBrokerに対するMQTT BrokerとMQTT クライアントの間でのメッセージ到達保証についてのパラメーターです。したがって、特定のトピックに対してのQoS 1でPublishが成功したとしても、同一に対してのSubscriberが存在し、そのメッセージに対しての適切な処理を行ったことを保証するものではありません。)
MQTTをご存じの方は、Retention flagをメッセージに付与すればよいのではないか?あるいは、Persistent Sessionを使えばよいのではないか?というご意見もあるかもしれません。筆者の理解する限りでは、もちろんこれらの機能を適切に使えば堅牢なシステムを構築することも可能ではあると思われますが、どちらも銀の弾丸ではなく、Retention Flagの場合には、1トピックあたり、1メッセージに限定される、また、Persistent Sessionを使った場合も、当然メッセージを保持する容量はサーバーリソースに限定されるので、すべてのデータを確実に保持することができるわけではない、という制限が付きます。ですので、すべてのTopicに対してこのような処理を行うかどうか、どのようなTopicに対してどのようなメッセージ戦略を取るか、どのようにサーバーリソースを確保するか、等適切なシステム設計が必要になると思われます。
一方、MODEプラットフォームでは、アプリケーションサーバーが直接MQTTを介してIoTデバイスと通信をしており、特定のトピックに対してPublishされたメッセージに対してQoSに応じて、ある種の処理が確実に行われることを保証します。QoSが1であればPubackを返しますが、この際に、トピック毎に定義されているアプリケーション的な動作を行った上で、Pubackを返しています。例えば、先に紹介したBulkDataトピックにメッセージがPublishされた場合、MODEプラットフォームのMQTTサーバーはデータを内部的なBlobストレージにデータを保存しつつ、後続処理を行うために内部的なメッセージキューにエンキューを行います。なお、過去のブログエントリーでデータの到達保証の難しさについて書かせて頂きましたが、弊社Gateway製品におけるデータ到達保証はこのBulkDataトピックを利用して実現しています。
最後に
その他にもアプリケーションサーバーが直接MQTTをしゃべることで実現することは他にもあるのと、それを実現するための技術的なトリックもいくつかあるのですが、それは別の機会に書かせて頂ければと思います。
近年では、オープンソースのMQTT Brokerアプリケーションも色々とありますし、Hive MQ等のMQTT Brokerサービスや、AWS IoTのようにMQTT Brokerを含む様々なIoT管理機構をあわせたプラットフォームが存在し、気軽に利用できるようになっていると思われます。ただし、メッセージングシステムは本質的に分散システムならではのアプリケーション設計の難しさをはらむことに注意しなければなりません。もちろん、エンジニアとして腕がなる部分でもあるので挑戦してみるのも楽しいと思います!一方、このような努力をすることよりも、本質的なIoTビジネスを実現するための開発に注力したいという方はMODEプラットフォームがその一助になるのではないかとも思います。MODEのIoT製品開発プログラム MODE Labs という形で、導入サポートも含めて対応可能ですので、ご興味ある方はぜひご覧ください。
その他業種ごとのデータ収集・分析ソリューションについては下記の事例集をご覧ください。
※ 別媒体からの転載記事です。
※ 掲載内容は2020年5月当時のものです。