MQTT の Session State についてざっくり理解する
Session とは何か
Client Identifier(クライアントID)で識別される、クライアントとの接続を一意に表す概念。つまり、同じクライアントIDの接続が2つ以上同時に存在することはできない[1]。
Session State とは何か
文字通り、Sessionの状態を指す。以下の2つの状態がある。
- サブスクライブ状態
クライアントがどのトピックをどのQoSでサブスクライブしているか、という情報の集合。 - 未完了のパブリッシュ・シーケンスの状態
PUBLISHパケットやPUBRELパケットを送信したが、その応答パケットが返ってきていない、という情報の集合。これは、QoS1、QoS2にのみ適用される。
ブローカーは、以下の2つのいずれかの条件を満たすとき、Session Stateを維持する。
- クライアントが接続されている
- クライアントが切断されているが、
Session Stateの有効期限が切れていない
有効期限の設定方法
MQTTのバージョンで違いがある。
MQTT V3.1.1の場合
そもそも有効期限の規定がない。
CONNECTパケット送信時にConnect FlagsのCrean Sessionに0を指定することで、以前のSessionがあればそのSessionが使用される。1を指定した場合は、それまでのSessionは破棄され新しいSessionが作成される。
MQTT V5.0の場合
MQTT V3.1.1のCrean SessionはMQTT V5.0ではCrean Startに変更されている。また、CONNECTパケットのSession Expiry Intervalのプロパティに秒数を指定することで設定できる。
Session Expiry Intervalが
- 省略されたとき
0扱いとなる。 -
0のとき
ブローカーはクライアントとの切断後にSession Stateを維持しない。 -
0でないとき
ブローカーはクライアントとの切断後も指定された秒数だけSession Stateを維持する。 -
0xFFFFFFFFのとき
Session Stateの有効期限は無期限という扱いになる。
動作イメージ

クライアントAとブローカーの間で以下のようなやり取りが行われる:
-
クライアントAがブローカーに接続する際、
CONNECTパケットを送信し、Session Expiry Intervalを例えば300秒に指定する。これにより、クライアントAとブローカー間の接続が切断された後も、ブローカーはクライアントAのSession Stateを300秒間維持するようになる。 -
クライアントAは
/hello/worldというトピックをSubscribeする。ブローカーは、クライアントAのSession Stateを維持する。このSession Stateには、クライアントAがSubscribeしているトピック(/hello/world)の情報が含まれている。 -
その後、何らかの理由でクライアントAとブローカー間の接続が切断されたとする。この時点から、ブローカーはクライアントAの
Session Stateを300秒間維持し続ける。 -
接続が切断されている間に、別のクライアントであるクライアントBが
/hello/world宛てのメッセージをPublishしたとする。ブローカーは、クライアントAのSession Stateを維持しているため、このメッセージを破棄せずに保持する。 -
300秒が経過する前にクライアントAがMQTTブローカーに再接続すると、ブローカーは維持していたクライアントAの
Session Stateを再利用する。これにより、クライアントAは以前にSubscribeしていたトピック(/hello/world)を再度Subscribeする必要がなくなる。また、ブローカーが保持していたメッセージ(クライアントBがPublishしたメッセージ)がクライアントAに配信される。
このように、Session Expiry Intervalを設定することで、一時的な接続の切断があっても、クライアントとブローカー間のSession Stateが維持され、メッセージの損失を防ぐことができる。
参考
-
AWS IoTのブローカーの場合、あるクライアントIDを持つクライアントAがブローカーに接続している状態で同一のクライアントIDを持つクライアントBが接続すると、元々接続していたクライアントAの接続が切断される、という動作をする。 ↩︎
Discussion