MQTT 持久會話和清理會話 說明
https://www.emqx.com/en/blog/mqtt-session
目錄
- MQTT 持久性會話
- 持久性會話需要儲存哪些資料?
- 使用 MQTT 乾淨會話
- MQTT 5.0 中的會話改進
- MQTT 會話問答
- 概括摘要
MQTT 持久性會話
網路不穩定和硬體資源有限是物聯網應用需要面對的兩大問題。由於網路波動和資源限制,MQTT 用戶端和代理之間的連線隨時可能異常斷開。為了解決網路斷開對通訊的影響,MQTT協定提供了持久會話(Persistent Session)。
MQTT 用戶端可以設定在發起與伺服器的連線時是否使用持久性會話。持久性會話將保存一些重要數據,以允許會話在多個網路連接上繼續。持久會話主要有以下三個功能:
- 避免因網路中斷而需要重複訂閱的額外開銷。
- 避免在離線期間遺失訊息。
- 確保 QoS 1 和 QoS 2 訊息不受網路中斷的影響。
持久性會話需要儲存哪些資料?
從上面我們知道,持久性會話需要儲存一些重要的數據,以便會話能夠恢復。其中一些資料儲存在客戶端,有些儲存在伺服器端。
客戶端保存的Session資料:
- QoS 1 和 QoS 2 訊息已傳送到伺服器,但尚未完成確認。
- 從伺服器收到但尚未完成確認的 QoS 2 訊息。
伺服器中儲存的會話資料:
- 會話是否存在,即使其餘會話狀態為空。
- 已傳送給客戶端但尚未完成確認的 QoS 1 和 QoS 2 訊息。
- 等待傳輸到客戶端的 QoS 0 訊息(可選)、QoS 1 和 QoS 2 訊息。
- 從客戶端收到但尚未完成確認的 QoS 2 訊息、Will 訊息和 Will Delay 間隔。
使用 MQTT 乾淨會話
Clean Session是一個標誌位,用來控制會話狀態的生命週期。值為1表示連線時將建立一個全新的會話,當客戶端中斷連線時該會話將自動銷毀。如果為0,則表示連線時會嘗試重複使用先前的會話。如果沒有對應的會話,則會建立一個新的會話,該會話在用戶端斷開連線後一直存在。
注意:僅當客戶端使用固定客戶端 ID 再次連線時,才能恢復持久性會話。如果用戶端 ID 是動態的,則連線成功後將建立一個新的持久性會話。
以下是開源 MQTT 伺服器 EMQX的 Dashboard 。可以看到圖中的連接已斷開,但由於是Persistent Session,所以仍然可以在Dashboard中查看。
EMQX 也支援在 Dashboard 中設定會話相關參數。
MQTT 3.1.1 沒有指定持久會話何時過期;如果單獨從協議層面來理解,這個持久會話應該是永久的。然而,這在現實場景中並不實用,因為它佔用了伺服器端的大量資源。因此,伺服器通常不會嚴格遵循協議,而是向使用者提供全域配置來限制會話過期時間。
例如, EMQ 提供的Free Public MQTT Broker設定會話過期時間為 5 分鐘,最大訊息數為 1000 條,且不儲存 QoS 0 訊息。
接下來,我們將示範 Clean Session 與開源跨平台MQTT 5.0 桌面用戶端工具 MQTTX的使用。
開啟MQTTX後,點選New Connection
按鈕建立MQTT連接,如下圖。
建立一個名為MQTT_V3
Clean Session off(即 false)的連接,並選擇 MQTT 版本 3.1.1,然後按一下Connect
右上角的 按鈕。
預設連接的伺服器是EMQ 提供的Free Public MQTT Broker 。
clean_session_false
連線成功且 QoS 設定為 1 後訂閱主題。
訂閱成功後,點選Disconnect
右上角按鈕。然後,再次建立名為 的連接MQTT_V3_Publish
,並將 MQTT 版本設定為 3.1.1,並clean_session_false
在連接成功後向主題發布兩個 QoS 1 訊息。
然後,選擇MQTT_V3連接並點擊Connect
按鈕連接到伺服器。您將成功收到兩條在離線期間發布的訊息。
MQTT 5.0 中的會話改進
在 MQTT 5.0 中,Clean Session 分為 Clean Start 和 Session Expiry Interval。Clean Start 指定連線時是建立新會話還是嘗試重複使用現有會話。會話過期間隔用於指定網路連線中斷後會話將過期的時間。
Clean Start oftrue
意味著必須丟棄任何現有會話,並建立一個全新的會話;false
表示必須使用與客戶端 ID 關聯的會話來恢復與客戶端的通訊(除非該會話不存在)。
Session Expiry Interval 解決了 MQTT 3.1.1 中持久性會話永久存在導致的伺服器資源浪費問題。設定為 0 或無表示會話在斷開連線時過期。大於 0 的值表示網路連線關閉後會話將保留多少秒。設定0xFFFFFFFF
意味著會話永遠不會過期。
更多詳細資訊請參閱部落格:Clean Start and Session Expiry Interval。
MQTT 會話問答
當會話結束時,保留的訊息還存在嗎?
MQTT 保留訊息不是會話狀態的一部分,並且不會在會話結束時刪除。
客戶端如何知道目前會話是恢復會話?
MQTT 協定從 v3.1.1 開始為 CONNACK 訊息設計了 Session Present 欄位。當伺服器為此欄位傳回值1時,表示目前連線將重複使用伺服器儲存的會話。連線成功後用戶端可以根據該欄位值決定是否重新訂閱。
使用持久會話的最佳實踐
- 您不能使用動態客戶端 ID。您需要確保每個客戶端連線的客戶端 ID 都是固定的。
- 根據伺服器效能、網路狀況、用戶端類型等合理評估會話過期時間。設定太長會佔用更多伺服器端資源。並且設定太短會導致會話在重新連接成功之前就過期了。
- 當用戶端確定不再需要該會話時,可以使用 Clean Session 為 true 重新連接,然後在重新連接成功後中斷連線。對於MQTT 5.0,您可以在斷開連線時直接將Session Expiry Interval設為0,表示連線中斷時會話將會過期。
概括摘要
至此,我們已經完成了 MQTT Persistent Session 的介紹,並透過桌面用戶端示範了 Clean Session 的使用。您可以參考本文使用MQTT持久會話接收離線訊息並減少訂閱開銷。
接下來,您可以查看EMQ 提供的《MQTT 協議通俗指南》系列文章,以了解 MQTT 主題、通配符、保留訊息、遺囑訊息等特性。探索 MQTT 的更高級應用程式並開始 MQTT 應用程式和服務開發。
沒有留言:
張貼留言