2023年11月18日 星期六

MQTT QoS 0, 1, 2 解釋:快速入門指南

 MQTT QoS 0, 1, 2 解釋:快速入門指南

https://www.emqx.com/en/blog/introduction-to-mqtt-qos
週子波
2023 年 1 月 12 日
MQTT QoS 0, 1, 2 解釋:快速入門指南

目錄

  • 什麼是服務品質
  • QoS 0 - 最多一次
  • QoS 1 - 至少一次
  • QoS 2 - 恰好一次
  • 場景和注意事項
  • 問答
  • 結論

什麼是服務品質

在不穩定的網路環境中,MQTT 設備可能難以僅使用 TCP 傳輸協定來確保可靠的通訊。為了解決這個問題,MQTT 提供了服務品質 (QoS) 機制,提供多種訊息互動選項,以提供不同層級的服務,滿足使用者在不同場景下可靠訊息傳遞的特定要求。

MQTT 中有 3 個 QoS 等級:

  • QoS 0,最多一次。
  • QoS 1,至少一次。
  • QoS 2,剛好一次。

這些等級對應於訊息傳遞的可靠性等級的提高。QoS 0 可能會遺失訊息,QoS 1 保證訊息傳遞,但可能存在重複訊息,QoS 2 保證訊息只傳遞一次而不重複。隨著QoS等級的提高,訊息傳遞的可靠性也隨之提高,但傳輸過程的複雜性也隨之提高。

在發布者到訂閱者的傳遞過程中,發布者在 PUBLISH 資料包中指定訊息的 QoS 層級。代理通常將訊息轉發給具有相同 QoS 等級的訂閱者。然而,在某些情況下,訂戶的要求可能需要降低轉送訊息的 QoS 等級。

例如,如果訂閱者指定他們只想接收 QoS 等級為 1 或更低的訊息,則代理會將所有 QoS 2 訊息降級為 QoS 1,然後再轉發給該訂閱者。QoS 0 和 QoS 1 的訊息將在原始 QoS 等級不變的情況下傳送給訂閱者。

MQTT QoS 降級

讓我們看看 QoS 是如何運作的。

QoS 0 - 最多一次

QoS 0 是最低服務級別,也稱為「即發即忘」。在這種模式下,發送方不會等待確認或儲存並重傳訊息,因此接收方無需擔心收到重複的訊息。

MQTT 服務品質 0

為什麼QoS 0訊息遺失?

QoS 0訊息傳輸的可靠性取決於TCP連線的穩定性。如果連線穩定,TCP就能保證訊息的成功傳遞。但是,如果連線關閉或重置,則存在傳輸中的訊息或作業系統緩衝區中的訊息可能遺失的風險,從而導致 QoS 0 訊息傳送失敗。

QoS 1 - 至少一次

為了確保訊息傳遞,QoS 1 引入了確認和重傳機制。當發送方收到接收方的 PUBACK 封包時,就認為訊息發送成功。在此之前,發送方必須儲存 PUBLISH 封包以備可能的重傳。

發送方使用每個資料包中的資料包 ID 將 PUBLISH 資料包與對應的 PUBACK 資料包進行比對。這允許發送方識別並從其快取中刪除正確的 PUBLISH 封包。

MQTT 服務品質 1

為什麼 QoS 1 訊息重複?

有兩種情況傳送者不會收到 PUBACK 封包。

  1. PUBLISH 封包未到達接收方。
  2. PUBLISH 封包已到達接收方,但發送方尚未收到接收方的 PUBACK 封包。

在第一種情況下,發送方將重傳PUBLISH資料包,但接收方只會收到該訊息一次。

在第二種情況下,發送方將重傳PUBLISH資料包,接收方將再次收到它,從而導致重複訊息。

MQTT QoS 1 重複

即使重傳的 PUBLISH 封包中的 DUP 標誌被設定為 1 以指示它是重複訊息,接收方也不能假設它已經收到該訊息,並且仍然必須將其視為新訊息。

這是因為,當接收方收到DUP標誌為1的PUBLISH報文時,有兩種可能的情況:

MQTT 服務品質 1 DUP

在第一種情況下,發送方因為沒有收到 PUBACK 封包而重傳 PUBLISH 封包。接收方收到兩個具有相同資料包 ID 的 PUBLISH 資料包,且第二個 PUBLISH 資料包的 DUP 標誌為 1。第二個資料包確實是重複訊息。

在第二種情況下,原始 PUBLISH 封包已成功傳遞。然後,該資料包 ID 用於新的、不相關的訊息。但是這條新訊息第一次發送時並沒有成功傳遞到對端,所以又重傳了。最後,重傳的 PUBLISH 封包將具有相同的封包 ID 和 DUP 標誌為 1,但它是一條新訊息。

由於無法區分這兩種情況,接收方必須將所有 DUP 標誌為 1 的 PUBLISH 封包視為新訊息。這意味著在使用QoS 1時,協定層不可避免地會出現重複訊息。

在極少數情況下,代理程式可能會從發布者收到重複的 PUBLISH 資料包,並在將它們轉發到訂閱者的過程中再次重新傳輸它們。這可能會導致訂閱者收到額外的重複訊息。

例如,雖然發布者只發送一條訊息,但接收者最終可能會收到三個相同的訊息。

MQTT QoS 1 重複

這些是使用 QoS 1 的缺點。

QoS 2 - 恰好一次

與QoS 0 和1 不同,QoS 2 確保訊息不會遺失或重複。但是,它也具有最複雜的互動和最高的開銷,因為它需要在每個訊息的發送者和接收者之間至少有兩個請求/響應流送貨。

MQTT 服務品質 2

  1. 要啟動 QoS 2 訊息傳輸,發送方首先儲存並發送 QoS 2 的 PUBLISH 封包,然後等待來自接收方的 PUBREC 回應封包。此流程與 QoS 1 類似,不同之處在於回應資料包是 PUBREC 而非 PUBACK。
  2. 收到 PUBREC 封包後,傳送者可以確認接收方已收到 PUBLISH 封包,並可刪除其本機儲存的副本。不再需要也無法重傳該資料包。然後,發送方發送 PUBREL 封包,通知接收方已準備好釋放封包 ID。與 PUBLISH 資料包一樣,PUBREL 資料包需要可靠地傳遞到接收方,因此需要儲存它以備可能的重傳,並且需要回應資料包。
  3. 當接收方收到PUBREL資料包時,可以確認在該傳輸流中不會再接收到額外的重傳的PUBLISH資料包。結果,接收方以 PUBCOMP 資料包回應,以表示它已準備好將目前資料包 ID 重新用於新訊息。
  4. 當發送方收到 PUBCOMP 封包時,QoS 2 流程完成。然後,發送方可以使用目前資料包 ID 發送新訊息,接收方會將其視為新訊息。

為什麼 QoS 2 訊息不重複?

確保QoS 2訊息不遺失的機制與QoS 1相同,因此這裡不再討論。

與QoS 1相比,QoS 2透過增加涉及PUBREL和PUBCOMP封包的新進程來確保訊息不重複。

在繼續深入之前,我們先快速回顧一下 QoS 1 無法避免訊息重複的原因。

當我們使用 QoS 1 時,對於接收方來說,發送 PUBACK 封包後,無論回應是否已到達發送方,封包 ID 都會再次可用。這意味著接收方無法確定其稍後收到的具有相同Packet ID 的PUBLISH 資料包是否是發送方因未收到PUBACK 回應而重傳的,或者發送方是否在之後重用了該Packet ID 發送了新訊息接收 PUBACK 回應。這就是QoS 1無法避免訊息重複的原因。

MQTT PUBACK

在 QoS 2 中,傳送者和接收者使用 PUBREL 和 PUBCOMP 封包來同步封包 ID 的釋放,確保傳送者在重傳訊息還是傳送新訊息方面達成共識。這是避免 QoS 1 中可能出現的重複訊息問題的關鍵。

MQTT PUBREL 和 PUBCOMP

在 QoS 2 中,允許發送方在從接收方接收 PUBREC 封包之前重傳 PUBLISH 封包。發送方一旦收到PUBREC並傳送PUBREL封包,就進入Packet ID釋放流程。發送方在收到來自接收方的 PUBCOMP 資料包之前,無法重傳 PUBLISH 資料包或使用目前資料包 ID 傳送新訊息。

MQTT 公共記錄

因此,接收方可以使用 PUBREL 封包作為邊界,並將在其先前到達的任何 PUBLISH 封包視為重複封包,並將在其之後到達的任何 PUBLISH 封包視為新封包。這使我們能夠在使用 QoS 2 時避免協議層級的訊息重複。

可能發生的事態和注意事項

服務品質 0

QoS 0 的主要缺點是訊息可能會遺失,具體取決於網路狀況。這意味著如果您斷開連接,您可能會錯過訊息。然而,QoS 0 的優點是訊息傳遞更有效率

因此,它通常用於發送高頻、不太重要的數據,例如定期感測器更新,其中錯過一些更新是可以接受的。

服務品質1

QoS 1 確保訊息至少傳遞一次,但可能會導致訊息重複。這使得它適合傳輸重要數據,例如關鍵指令或重要狀態的即時更新。然而,在決定使用不含重複資料刪除的 QoS 1 之前,考慮如何處理或允許此類重複很重要。

例如,如果發布者按照 1、2 的順序發送訊息,但是訂閱者按照 1、2、1、2 的順序接收訊息,其中 1 代表開燈命令,2 代表關燈命令,由於重複的訊息,燈可能不希望重複打開和關閉。

MQTT 服務品質

服務品質2

QoS 2 確保訊息不會遺失或重複。然而,它的開銷也最高。如果使用者不願意自己處理訊息重複並且可以接受QoS 2的額外開銷,那麼它是一個合適的選擇。QoS 2 通常用於金融和航空等行業,在這些行業中,確保可靠的訊息傳遞並避免重複至關重要。

問答

如何刪除重複的 QoS 1 訊息?

由於QoS 1訊息重複是協議層面固有的,所以我們只能在業務層面解決這個問題。

消除重複 QoS 1 訊息的一種方法是在每個 PUBLISH 封包的有效負載中包含時間戳記或單調遞增計數。這允許您透過將當前訊息的時間戳記或計數與上次收到的訊息的時間戳記或計數進行比較來確定當前訊息是否為新訊息。

何時應將 QoS 2 訊息轉發給訂閱者?

據我們了解,QoS 2 的開銷很高。為了避免影響 QoS 2 訊息的即時性,最好在第一次收到 QoS 2 PUBLISH 封包時啟動將訊息轉發給訂閱者的程序。然而,一旦啟動此過程,在 PUBREL 封包之前到達的後續 PUBLISH 封包不應再次轉發,以防止訊息重複。

QoS 之間的性能有差異嗎?

當使用具有相同硬體配置的 EMQX 進行點對點通訊時,QoS 0 和 QoS 1 通常具有相似的吞吐量,但 QoS 1 可能具有更高的 CPU 使用率。此外,在高負載下,與 QoS 0 相比,QoS 1 的訊息延遲更長。另一方面,QoS 2 通常只有 QoS 0 和 1 的一半左右的吞吐量。

結論

到目前為止,您應該對 MQTT QoS 有了透徹的了解。如需繼續學習 MQTT,您可以查看 EMQ 的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...