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