在這篇文章中,解釋了 MQTT 中不同的服務(wù)質(zhì)量級別。“服務(wù)質(zhì)量”這個詞在之前的文章中出現(xiàn)過幾次,讓我們來看看這個詞到底是什么意思。
正文
什么是服務(wù)質(zhì)量?
- 服務(wù)質(zhì)量水平(QoS)是一個消息的發(fā)送者和限定遞送保證用于特定消息的消息的接收器之間的協(xié)議。MQTT 中有 3 個 QoS 級別:
1.最多一次(0)
2.至少一次(1)
3.恰好一次(2)。
在 MQTT 中談 QoS 時,需要考慮消息傳遞的兩個方面:
1.消息從發(fā)布客戶端傳遞到代理。
2.從代理到訂閱客戶端的消息傳遞。
我們將分別查看消息傳遞的兩個方面,因為兩者之間存在細微差別。向代理發(fā)布消息的客戶端在向代理發(fā)送消息時定義了消息的 QoS 級別。代理使用每個訂閱客戶端在訂閱過程中定義的 QoS 級別將此消息傳輸?shù)接嗛喛蛻舳恕?strong>如果訂閱客戶端定義的 QoS 低于發(fā)布客戶端,則代理會以較低的服務(wù)質(zhì)量傳輸消息。
為什么服務(wù)質(zhì)量很重要?
- QoS 是 MQTT 協(xié)議的一個關(guān)鍵特性。QoS 使客戶端能夠選擇與其網(wǎng)絡(luò)可靠性和應(yīng)用程序邏輯相匹配的服務(wù)級別。因為 MQTT 管理消息的重新傳輸并保證交付(即使底層傳輸不可靠),QoS 使不可靠網(wǎng)絡(luò)中的通信變得更加容易。
它是如何工作的?
- 讓我們仔細看看每個 QoS 級別在 MQTT 協(xié)議中是如何實現(xiàn)的,以及它是如何運作的:
-
QoS 0 - 最多一次 (服務(wù)質(zhì)量級別 0:最多交付一次)
最低 QoS 級別為零。此服務(wù)級別可確保盡最大努力交付。不保證交貨。接收方不會確認收到消息,并且消息不會被發(fā)送方存儲和重新傳輸。QoS 級別 0 通常被稱為“即發(fā)即忘”,并提供與底層 TCP 協(xié)議相同的保證。

-
QoS 1 - 至少一次 (服務(wù)質(zhì)量級別 1:至少交付一次)
QoS 級別 1 保證消息至少傳遞一次給接收者。發(fā)送方存儲消息,直到它從接收方收到確認收到消息的 PUBACK數(shù)據(jù)包。一條消息可以多次發(fā)送或傳遞。

發(fā)送方使用每個數(shù)據(jù)包中的數(shù)據(jù)包標識符將 PUBLISH 數(shù)據(jù)包與相應(yīng)的 PUBACK 數(shù)據(jù)包進行匹配。如果發(fā)送方在合理的時間內(nèi)沒有收到 PUBACK 數(shù)據(jù)包,則發(fā)送方重新發(fā)送 PUBLISH 數(shù)據(jù)包。當接收者收到 QoS 1 的消息時,它可以立即處理它。例如,如果接收方是代理,則代理將消息發(fā)送給所有訂閱客戶端,然后回復(fù)一個 PUBACK 數(shù)據(jù)包。

如果發(fā)布客戶端再次發(fā)送消息,它會設(shè)置重復(fù) (DUP) 標志。在 QoS 1 中,此 DUP 標志僅用于內(nèi)部目的,不由代理或客戶端處理。無論 DUP 標志如何,消息的接收者都會發(fā)送 PUBACK。
-
QoS 2 - 恰好一次 (服務(wù)質(zhì)量級別 2:僅交付一次)
QoS 2 是 MQTT 中最高級別的服務(wù)。此級別保證每條消息僅被預(yù)期收件人接收一次。QoS 2 是最安全、最慢的服務(wù)質(zhì)量級別。該保證由發(fā)送方和接收方之間的至少兩個請求/響應(yīng)流(四部分握手)提供。發(fā)送方和接收方使用原始 PUBLISH 消息的數(shù)據(jù)包標識符來協(xié)調(diào)消息的傳遞。

當接收方從發(fā)送方獲得 QoS 2 PUBLISH 數(shù)據(jù)包時,它會相應(yīng)地處理發(fā)布消息并使用PUBREC數(shù)據(jù)包回復(fù)發(fā)送方以確認 PUBLISH 數(shù)據(jù)包。如果發(fā)送方?jīng)]有從接收方得到 PUBREC 數(shù)據(jù)包,它會再次發(fā)送帶有重復(fù) (DUP) 標志的 PUBLISH 數(shù)據(jù)包,直到它收到確認為止。

一旦發(fā)送方收到來自接收方的 PUBREC 數(shù)據(jù)包,發(fā)送方就可以安全地丟棄初始的 PUBLISH 數(shù)據(jù)包。發(fā)送方存儲來自接收方的 PUBREC 數(shù)據(jù)包,并以PUBREL數(shù)據(jù)包進行響應(yīng) 。

接收方得到PUBREL報文后,可以丟棄所有存儲的狀態(tài),用PUBCOMP報文應(yīng)答(發(fā)送方收到PUBCOMP報文也是如此)。在接收方完成處理并將 PUBCOMP 數(shù)據(jù)包發(fā)送回發(fā)送方之前,接收方存儲對原始 PUBLISH 數(shù)據(jù)包的數(shù)據(jù)包標識符的引用。此步驟對于避免再次處理消息很重要。發(fā)送方收到 PUBCOMP 數(shù)據(jù)包后,已發(fā)布消息的數(shù)據(jù)包標識符可供重復(fù)使用。
當 QoS 2 流完成時,雙方都確定消息已傳遞,并且發(fā)送方已確認傳遞。
如果數(shù)據(jù)包在途中丟失,則發(fā)送方有責任在合理的時間內(nèi)重新傳輸消息。如果發(fā)送方是 MQTT 客戶端或MQTT 代理則同樣如此。接收方有責任相應(yīng)地響應(yīng)每個命令消息。
關(guān)于QoS
QoS 的某些方面乍一看并不是很明顯。當您使用 QoS 時,請記住以下幾點:
QoS降級
正如上文已經(jīng)提到,發(fā)送(發(fā)布)消息的客戶端和接收消息的客戶端之間的 QoS 定義和級別是兩件不同的事情。這兩種交互的 QoS 級別也可以不同。向代理發(fā)送 PUBLISH 消息的客戶端定義消息的 QoS。但是,當代理將消息傳遞給接收者(訂閱者)時,代理使用接收者(訂閱者)在訂閱期間定義的 QoS。例如,客戶端 A 是消息的發(fā)送者。客戶端 B 是消息的接收者。如果客戶端 B 以 QoS 1 訂閱代理并且客戶端 A 以 QoS 2 向代理發(fā)送消息,則代理以 QoS 1 將消息傳遞給客戶端 B(接收者/訂閱者)。消息可以多次傳遞給客戶端乙,每個客戶端的數(shù)據(jù)包標識符是唯一的
MQTT 用于 QoS 1 和 QoS 2 的數(shù)據(jù)包標識符在交互中的特定客戶端和代理之間是唯一的。此標識符在所有客戶端之間不是唯一的。一旦流完成,數(shù)據(jù)包標識符就可以重新使用。這種重用是包標識符不需要超過65535的原因??蛻舳丝梢栽诓煌瓿山换サ那闆r下發(fā)送超過這個數(shù)量的消息是不現(xiàn)實的。
最佳實踐
- 我們經(jīng)常被問到如何選擇正確的 QoS 級別的建議。以下是一些可以幫助您進行決策的指南。適合您的 QoS 在很大程度上取決于您的用例。
當……時使用 QoS 0
- 您在發(fā)送方和接收方之間建立了完全或大部分穩(wěn)定的連接。QoS 0 的一個經(jīng)典用例是通過有線連接將測試客戶端或前端應(yīng)用程序連接到 MQTT 代理。
- 您不介意偶爾丟失幾條消息。如果數(shù)據(jù)不是那么重要或數(shù)據(jù)間隔很短,則某些消息的丟失是可以接受的
- 您不需要消息隊列。僅當斷開連接的客戶端具有 QoS 1 或 2 和持久會話時,消息才會排隊 。
當……時使用 QoS 1
- 您需要獲取每條消息,并且您的用例可以處理重復(fù)項。QoS 級別 1 是最常用的服務(wù)級別,因為它保證消息至少到達一次,但允許多次傳遞。當然,您的應(yīng)用程序必須容忍重復(fù)并能夠相應(yīng)地處理它們。
- 您無法承受 QoS 2 的開銷。QoS 1 傳遞消息的速度比 QoS 2 快得多。
當……時使用 QoS 2
- 一次接收所有消息對您的應(yīng)用程序至關(guān)重要。如果重復(fù)交付可能損害應(yīng)用程序用戶或訂閱客戶端,則通常會出現(xiàn)這種情況。請注意開銷以及 QoS 2 交互需要更多時間才能完成。
QoS 1 和 2 消息的排隊
- 使用 QoS 1 和 2 發(fā)送的所有消息都會排隊等待離線客戶端,直到客戶端再次可用。但是,這種排隊只有在客戶端具有持久會話時才有可能 。