2023年11月18日 星期六

MQTT 持久會話和清理會話解釋

 MQTT 持久會話和清理會話 說明

https://www.emqx.com/en/blog/mqtt-session

週子波
2022 年 12 月 27 日
MQTT 持久會話和清理會話解釋

目錄

  • 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中查看。

MQTT 連接

EMQX 也支援在 Dashboard 中設定會話相關參數。

MQTT 會話

MQTT 3.1.1 沒有指定持久會話何時過期;如果單獨從協議層面來理解,這個持久會話應該是永久的。然而,這在現實場景中並不實用,因為它佔用了伺服器端的大量資源。因此,伺服器通常不會嚴格遵循協議,而是向使用者提供全域配置來限制會話過期時間。

例如, EMQ 提供的Free Public MQTT Broker設定會話過期時間為 5 分鐘,最大訊息數為 1000 條,且不儲存 QoS 0 訊息。

接下來,我們將示範 Clean Session 與開源跨平台MQTT 5.0 桌面用戶端工具 MQTTX的使用。

開啟MQTTX後,點選New Connection按鈕建立MQTT連接,如下圖。

按一下新建連接

建立一個名為MQTT_V3Clean Session off(即 false)的連接,並選擇 MQTT 版本 3.1.1,然後按一下Connect右上角的 按鈕。

預設連接的伺服器是EMQ 提供的Free Public MQTT Broker 。

建立連接

clean_session_false連線成功且 QoS 設定為 1 後訂閱主題。

訂閱 clean_session_false 主題

訂閱成功後,點選Disconnect右上角按鈕。然後,再次建立名為 的連接MQTT_V3_Publish,並將 MQTT 版本設定為 3.1.1,並clean_session_false在連接成功後向主題發布兩個 QoS 1 訊息。

發布 MQTT 訊息

然後,選擇MQTT_V3連接並點擊Connect按鈕連接到伺服器。您將成功收到兩條在離線期間發布的訊息。

接收 MQTT 訊息

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 應用程式和服務開發。

沒有留言:

張貼留言

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...