MQTT の Will についてざっくり理解する
はじめに
MQTTはHTTPと比較すると軽量で双方向通信が可能なため、計算リソースの乏しいデバイスを使わざるを得ないことが多いIoTの分野に向いているとされる通信プロトコルです。AWSではAWS IoTというサービスでマネージドでサーバーレスなMQTTブローカー(MQTTサーバー)が提供されています。ちなみにGoogle CloudでもGoogle Cloud IoT Coreという名称で同様のサービスが提供されていましたが、残念ながら2023年8月にサービス提供終了となってしまいました。
さて、MQTTの機能の1つにWillという機能がありますが、最近どんなものだったっけ?となったので調べてみました。
※この記事の内容は、MQTT V3.1.1、5の両方に当てはまる内容です。
Willとは何か
クライアントとMQTTブローカー間の接続が切断されたしまったときにPublishするメッセージを予めMQTTブローカーに登録しておける機能です。メッセージと一緒に登録するMQTTトピックをSubscribeしておいた別のクライアントは、このメッセージを受け取ることができます。
いつ死んでも(?)良いようにメッセージを残しておく機能を遺書と表現したのは言い得て妙ですね。
動作イメージ
では具体的にどのような動作となるのか、シーケンス図でイメージを掴みたいと思います。
まずはWill Messsageを残すクライアントAの動作です。クライアントAは接続要求のパケット(CONNECT)に、Will Flag(1にセット)、Will Message、Will Topicを含めてMQTTブローカーに送信します。このパケットを受け取ったMQTTブローカーはWill MessageとWill Topicの情報を保持しておきます。
次に、Will Messageを受け取りたいクライアントBは、Will TopicをSubscribeしておきます。
この状態でMQTTブローカーが接続断を検知すると、MQTTブローカーはWill TopicをSubscribeしているクライアントBに対し、保持していたWill MessageをPublishします。
ちなみに、クライアントからDISCONNECTパケットを送信し正常に接続が切断された場合は、Will MessageはPublishされません。
Will MessageがPublishされる接続断のケース
では、実際にどのような場合にWill MessageがPublishされるのでしょうか。例えば以下のようなケースがあります。
- MQTTブローカーがTCP/IPにおける接続断を検知した場合
- MQTTのKeep Aliveタイムアウトが発生した場合
- MQTTクライアントはMQTTブローカーに対しKeep Aliveに設定した間隔(この設定はCONNECTパケットに含まれます)でPINGREQパケットを送信することで自身が「生きていること」を知らせます。PINGREQを送信しないままKeep Aliveに指定した時間(MQTTの仕様としてはKeep Aliveに指定した時間の1.5倍)を超過してしまうと、MQTTブローカーはクライアントとの接続が失われたと判断し、接続を切断します。
使い所
MQTTクライアントとの間の正常ではない接続断を検知できるため、普通に考えるとMQTTクライアントの死活監視でしょうか。例えばAWSであればWill Topicに対するメッセージをルーティングするIoTルールを作成すれば、どこかに通知するなど柔軟に処理できそうです。
Discussion