服務質量
MQTT協議中規定了消息服務質量(Quality of Service),它保證了在不同的網絡環境下消息傳遞的可靠性,QoS 的設計是 MQTT 協議裏的重點。作爲專爲物聯網場景設計的協議,MQTT 的運行場景不僅僅是 PC,而是更廣泛的窄帶寬網絡和低功耗設備,如果能在協議層解決傳輸質量的問題,將爲物聯網應用的開發提供極大便利。
Qos值 | Bit2 | Bit1 | 描述 |
---|---|---|---|
0 | 0 | 0 | 最多分發一次 |
1 | 0 | 0 | 至少分發一次 |
2 | 0 | 0 | 只分發一次 |
- | 1 | 1 | 保留位 |
PUBLISH 報文的 2 個 QoS 比特位不能同時設置爲 1 。如果服務端或客戶端收到 QoS 2
個比特位都爲 1 的無效 PUBLISH 報文,使用包含原因碼爲 0x81(無效報文)的 DISCONNECT 報文關閉網絡連接
工作原理
QoS 0 - 最多分發一次
當 QoS 爲 0 時,消息的分發依賴於底層網絡的能力。發佈者只會發佈一次消息,接收者不會應答消息,發佈者也不會儲存和重發消息。消息在這個等級下具有最高的傳輸效率,但可能送達一次也可能根本沒送達。
Qos 1 - 至少分發一次
當 QoS 爲 1 時,可以保證消息至少送達一次。MQTT 通過簡單的 ACK 機制來保證 QoS 1。發佈者會發布消息,並等待接收者的 PUBACK 報文的應答,如果在規定的時間內沒有收到 PUBACK 的應答,發佈者會將消息的 DUP 置爲 1 並重發消息。接收者接收到 QoS 爲 1 的消息時應該回應 PUBACK 報文,接收者可能會多次接受同一個消息,無論 DUP 標誌如何,接收者都會將收到的消息當作一個新的消息併發送 PUBACK 報文應答。
QoS 2 - 只分發一次
當 QoS 爲 2 時,發佈者和訂閱者通過兩次會話來保證消息只被傳遞一次,這是最高等級的服務質量,消息丟失和重複都是不可接受的。使用這個服務質量等級會有額外的開銷。
發佈者發佈 QoS 爲 2 的消息之後,會將發佈的消息儲存起來並等待接收者回復 PUBREC 的消息,發送者收到 PUBREC 消息後,它就可以安全丟棄掉之前的發佈消息,因爲它已經知道接收者成功收到了消息。發佈者會保存 PUBREC 消息並應答一個 PUBREL,等待接收者回復 PUBCOMP 消息,當發送者收到 PUBCOMP 消息之後會清空之前所保存的狀態。
當接收者接收到一條 QoS 爲 2 的 PUBLISH 消息時,他會處理此消息並返回一條 PUBREC 進行應答。當接收者收到 PUBREL 消息之後,它會丟棄掉所有已保存的狀態,並回復 PUBCOMP。
無論在傳輸過程中何時出現丟包,發送端都負責重發上一條消息。不管發送端是 Publisher 還是 Broker,都是如此。因此,接收端也需要對每一條命令消息都進行應答。
報文標識符(Packet ID)
MQTT 協議規定每次發佈一個 QoS > 0 的消息的時候都必須分配一個當前未使用的非零報文標識符 [MQTT-2.2.1-4]。當處理完這個報文對應的確認後,這個報文標識符就釋放可重用,某個報文標識符在某一時刻不能被多個命令所使用。
發佈者和訂閱者
MQTT 發佈消息 QoS 不是端到端的,是客戶端與服務器之間的。訂閱者收到 MQTT 消息的 QoS 級別,最終取決於發佈消息的 QoS 和主題訂閱的 QoS。
如何選擇QoS
QoS 級別越高,流程越複雜,系統資源消耗越大。應用程序可以根據自己的網絡場景和業務需求,選擇合適的 QoS 級別,比如在同一個子網內部的服務間的消息交互往往選用 QoS 0;而通過互聯網的實時消息通信往往選用 QoS 1;QoS 2 使用的場景相對少一些,適合一些支付請求之類的要求較高的場景。