このエントリーをはてなブックマークに追加

MQTTについてのまとめ

注釈

MQTT As a Service: sangoをリリースしました

2014年8月に、GitHubアカウントで簡単に登録できてMQTTを使い始められるsango時雨堂がリリースしました。

無料プランもありますので、MQTTを一度使ってみたいという方はsangoを使うことをお勧めします。

最近voluntasさんが活動しており、にわかにMQTT関連が熱くなってきました。たぶん観測範囲が狭いからだとは思いますが。

とはいえ、M2M (Machine to Machine)やIoT(Internet of Things)というバズワードもあり、モノがインターネットにつながる時代になってきて、MQTTの価値が高くなってきている気もします。また、モバイル時代に適したプロトコルという意味でも注目されているのかもしれません。

ということ、MQTTについて一旦ここでまとめてみます。

MQTTとはなにか

MQTT(MQ Telemetry Transport) とは、publish/subscribeモデルに基づく軽量なメッセージプロトコルです。ネットワークが不安定な場所で動作するための機能や非力なデバイスで動くための軽量化などが特徴です。

MQと名前についていますが、負荷を分散させるためのいわゆる Job Queueではありません。そういう用途にはAMQPなどを使ってください。

MQTTはメッセージの配信に特化しており、特に多数のPublisher/Subscriberを持たなければいけない用途に使われています。また、軽量な点と同期通信な点を生かして、リアルタイム通信が必要な用途にも使われています。

具体的には

などが挙げられます。

歴史

MQTTは元々は1999年からIBMとEurotech社が策定していました。IBMはIBM MessageSightという製品を持っています。

その後 2011年にEclipse FoundationにMQTTのコードが寄贈され、また、2013年にOASISという国際標準化団体にて標準化が行われるようになりました。

仕様はロイヤリティフリーで公開されています。現在の仕様は3.1が最新で、近々3.1.1が登場します。

特徴

MQTTの特徴を簡単にまとめてみます。

  • 固定長2バイトというオーバーヘッドの少なさと処理の軽さ
  • 1対多、多対多のメッセージ配布、しかもTopic wildcardにより柔軟性が高い
  • アプリケーションの特性に合わせて三種類のQoSを指定可能
    • 「最高1回」「少なくとも一回」「正確に一回」の三種類
  • 切断が発生し、再接続後に切断中のメッセージを受け取れる「Durable subscribe」
  • Publish側が切断した場合に事前に決めておいたメッセージを流す「Last Will and Testament」
  • あとからSubscribeしてきた場合に送れるように、最後のメッセージを保存しておく「Retain」

QoS、WillなどはMQTTの特徴的な機能ですね。

なお、MQTTはTCP/IP上で動作し、payloadは仕様では特に決められていません。文字列が使わることも多いようですし、MessagePackを使っているという話も聞いたことがあります。

では、これらについて説明していきます。

軽量

MQTTは固定長ヘッダーが最小2バイトとオーバーヘッドが少なく、またプロコトルも単純です。そのため、HTTPに比べるとネットワーク帯域および処理速度に優れています。また、処理が少ないということで、消費電力も少なくなっており、モバイル機器にも向いています。

IBMの資料によると、HTTPに比べて

  • トラフィックが10分の1から100分の1に、すなわち、10〜100倍のスループット
  • 電池の消費量が10分の1以下に

とのことです。

また、HTTPのようにコネクションレスではなく、一定間隔でheart beatを送り合う、コネクション指向のプロトコルで、双方向通信を行います。そのため、即時性が高い通信が可能です。

性能ですが、別のIBMの資料では

  • Linux, 4 x 4-core 2.93GHz Intel Xeon with 32GB of RAM and 10Gbit LAN

  • 100,000 クライアント
  • 13,000メッセージ/sec

  • 25%のCPU

でさばいたそうです。これは一番軽量な場合(QoS0)ですが、一番重い場合(QoS2)でも、6000 メッセージ/secを30%のCPU loadでさばいたそうです。

Topic

メッセージはそれぞれ「Topic」を持っています。Topicは

/r_rudi/second_house/room10/light/watt

というように/区切りの階層構造になっています。

Subscriber側では、購読するTopicを指定します。この時完全に一致ではなく、Wildcardを指定できます。

例えば以下のように指定できます。

/r_rudi/second_house/room10/light/watt
完全一致指定
/r_rudi/second_house/#
/r_rudi/second_house/ 以下すべてのtopic
/r_rudi/second_house/+/light/watt
部分一致 (この場合、すべての部屋のlightのwattを得る)

もちろん一つのsubscriberが複数のtopicをsubscribeできます。

QoS

MQTTではメッセージ配信に関してQoSが設定できます。

  • QoS 0: At most once -- 最高1回。届くかは保証しない。
  • QoS 1: At least once -- 少なくとも一回。重複する可能性がある。
  • QoS 2: Exactly once -- 正確に一回

これは送信するメッセージごとに変更できますので、通常はQoS 0で届いても届かなくてもいいけれども、コントロールメッセージは必ず届くように QoS 1か2にする、などができます。

QoS 1と2については、ACKや再送の場合などもプロトコル仕様の中で定義されています。

Durable subscribe

MQTTはネットワークが不安定な状況を想定しています。そのため、QoS 1とQoS2の場合、送られたメッセージを一定期間サーバー(Broker)が保持しておきます。

Subscriberが明示的なDISCONNECTやUNSUBSCRIBEをせずに突然切断した場合、再接続してきた時にその間のメッセージを再送する機能があります。

これにより、不安定なネットワークやサーバーでも動作できるわけです。

Will

クライアントは最初にサーバーにCONNECTした時にWillという情報を追加できます。サーバーはそのクライアントとの通信ができなくなった場合に、このWillで指定されたTopicとPayloadを送信します。

これにより、Subscriber側でPublish側が死んだということを判断できるわけです。

なお、死活判定は、一定間隔ごとに送られるpingに答えるかどうかで判断されます。この間隔も接続のたびに決められますので、このデバイスは電池が心配だから間隔を長くしよう、などのようなことができます。

Retain

Retain機能とは、最後にPublishされたメッセージをMQTTサーバーが保持しておき、新しいSubscriberにそのメッセージを渡す機能です。

MQTTはPublish/Subscribe型モデルです。従って、Publishされた時にSubscribeしていたクライアントにしかメッセージは送信されません。そのため、例えば1時間ごとに更新される情報を得ようとSubscribeしても、最長1時間はなにも情報が得られないことになります。

しかし、この場合でもRetain機能を使うと最新の情報を得られます。

セキュリティ

MQTTは、最初にサーバー(Broker)に接続するときにユーザー名とパスワードを指定するようにできます。ただし、パスワード自体はクリアテキストで送られてくるのでSSLを通してセキュリティを構築することになっています。

また、Subscriberの認証もありませんので、このTopicはこのSubscriberだけに配信しよう、などということも仕様にはありません。ただ、後述のMosquittoはユーザー名ごとにReadとWriteのアクセス管理をできる機能が実装されています。

さきほどユーザー名とパスワードを指定すると書きましたが、この扱いについては実装依存です。通常の認証に加えて、LDAPやOAuthを使って認証をする、という実装も可能です。

実装

プロトコルが簡単ですので、実装は多くあります。ただ、QoS 0だけだったりと、きちんと実装されているものは多くありません。

その中で、よく参照されているものを列挙します。

MosquittoはCで書かれた古くからある実装で、ほぼすべての機能を実装しており、参照実装として扱われることが多いです。

RabbitMQはerlang製の定評あるMQサーバーです。AMQPなどにも対応していますが、MQTTにも対応しています。

Pahoは前述の通りIBMから寄贈された実装で、Java版やPython、JSなど、多彩な言語に対応しています。

ActiveMQ ApolloはMQTTTの他STOMPやAMQPなどもできます。

また、クローズドソースですが、HiveMQというものもあります。

注釈

時雨堂さんがMQTT Brokerを作っています。erlangという言語で実装されており、かなりの速度と耐故障性があるそうです。

残念ながらクローズドソースですが、そのspecや開発ログなどはこちらから参照できます。

WebSocket

WebSocketはHTTP上で双方向通信を行うプロトコルで、最近のブラウザであればだいたい動作します。

このプロトコルはMQTTの双方向通信と同じ機能を提供するため、ブラウザ上でWebSocketを使ってMQTTサーバーにつなげるライブラリもあります。

まとめ

最近微妙に少しだけほんのりと熱くなってきている気がしているけどそうでもないかもしれないMQTTについてまとめてみました。

軽いプロトコル、コネクション指向、切断検知や再送機能など、いろいろ使えそうなプロトコルです。案外多くの使い方にフィットするかもしれません。

「HTTPですべてを行う」のもいいですが、他のプロトコルも使ってみるのも一つの考え方かもしれません。

ちなみに、ぼくが書いたMQTT関連のソフトウェアは以下の3つです。どれもコンセプトレベルですけど、なにかの参考になれば。