👻

MQTTのWillについてざっくり理解する

2024/03/01に公開

はじめに

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