MQTT 協議學習:Retained(保留消息) 與 LWT(最后遺囑)


--- title: protocol-app-mqtt-testament date: 2020-02-05 10:36:51 categories: tags: - mqtt - protocol ---

背景導入

讓我們來看一下這個場景:

你有一個溫度傳感器,它每三個小時向一個 Topic 發布當前的溫度。那么問題來了,有一個新的訂閱者在它剛剛發布了當前溫度之后訂閱了這個主題,那么這個訂閱端什么時候能才能收到溫度消息?

對的,它必須等到三個小時以后,溫度傳感器再次發布消息的時候才能收到。在這之前,這個新的訂閱者對傳感器的溫度數據一無所知。

怎么來解決這個問題呢?

這個時候就輪到 Retained 消息出場解決這個問題了。Retained 消息是指在 PUBLISH 數據包中 Retain 標識設為 1 的消息,Broker 收到這樣的 PUBLISH 包以后,將保存這個消息,當有一個新的訂閱者訂閱相應主題的時候,Broker 會馬上將這個消息發送給訂閱者。

Retained 消息

Retain 消息有以下一些特點:

  • 一個 Topic 只能有 1 條 Retained 消息,發布新的 Retained 消息將覆蓋老的 Retained 消息;
  • 如果訂閱者使用通配符訂閱主題,它會收到所有匹配的主題上的 Retained 消息;
  • 只有新的訂閱者才會收到 Retained 消息,如果訂閱者重復訂閱一個主題,也會被當做新的訂閱者,然后收到 Retained 消息;
  • Retained 消息發送到訂閱者時,消息的 Retain 標識仍然是 1,訂閱者可以判斷這個消息是否是 Retained 消息,以做相應的處理。

注意:Retained 消息和持久性會話沒有任何關系,Retained 消息是 Broker 為每一個 Topic 單獨存儲的,而持久性會話是 Broker 為每一個 Client 單獨存儲的。

如果你想刪除一個 Retained 消息也很簡單,只要向這個主題發布一個 Payload 長度為 0 的 Retained 消息就可以了。

那么開頭我們提到的那個場景的解決方案就很簡單了,溫度傳感器每 3 個小時發布當前的溫度的 Retained 消息,那么無論新的訂閱者什么時候進行訂閱,它都能收到溫度傳感器上一次發布的數據。

LWT(最后遺囑)

LWT 全稱為 Last Will and Testament,也就是我們在連接到 Broker 時提到的遺囑,包括遺囑主題、遺囑 QoS、遺囑消息等。

顧名思義,當 Broker 檢測到 Client 非正常地斷開連接的時候,就會向遺囑主題里面發布一條消息。遺囑相關的設置是在建立連接的時候,在 CONNECT 數據包里面的 Variable header(可變頭與) Payload(有效載荷) 中 指定的。

  • Will Flag:是1否0使用 LWT
  • Will Topic:遺囑主題名,不可使用通配符(在 CONNECT報文中的 有效載荷 中 設置)
  • Will Qos:發布遺囑消息時使用的 QoS 等級,如果遺囑標志(Will Flag)被設置為0,遺囑QoS也必須設置為0(0x00)
  • Will Retain:遺囑消息的 Retain 標識
  • Will Message:遺囑消息內容(在 CONNECT報文中的 有效載荷 中 設置)

Broker 在以下情況下認為 Client 是非正常斷開連接的:

  • Broker 檢測到底層的 I/O 異常;
  • Client 未能在 Keep Alive 的間隔內和 Broker 之間有消息交互;
  • Client 在關閉底層 TCP 連接前沒有發送 DISCONNECT 數據包;
  • Broker 因為協議錯誤關閉和 Client 的連接,比如 Client 發送了一個格式錯誤的 MQTT 數據包。

如果 Client 通過發布 DISCONNECT 數據包斷開連接,這個屬於正常斷開連接,不會觸發 LWT 的機制,同時,Broker 還會丟棄掉這個 Client 在連接時指定的 LWT 參數。

根據遺囑的屬性和觸發機制,我們不難看出,遺囑常用於獲取設備的連接狀態。

注意,設置好遺囑以后還不夠(因為你只要訂閱者一啟動就會收到遺囑消息,如果此時發布者已經在線,會導致不准確),
所以,還需要在設備成功連接MQTT的時候主動發個消息,發送的主題必須和遺囑的主題相同,設置好消息的 retain 屬性,讓其自動糾正過來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM