QoS等級
- QoS0,At most once,至多一次;
- QoS1,At least once,至少一次;
- QoS2,Exactly once,確保只有一次。
QoS 是消息的發送方(Sender)和接受方(Receiver)之間達成的一個協議: - QoS0 代表,Sender 發送的一條消息,Receiver 最多能收到一次,也就是說 Sender 盡力向 Receiver 發送消息,如果發送失敗,也就算了;
- QoS1 代表,Sender 發送的一條消息,Receiver 至少能收到一次,也就是說 Sender 向 Receiver 發送消息,如果發送失敗,會繼續重試,直到 Receiver 收到消息爲止,但是因爲重傳的原因,Receiver 有可能會收到重複的消息;
- QoS2 代表,Sender 發送的一條消息,Receiver 確保能收到而且只收到一次,也就是說 Sender 盡力向 Receiver 發送消息,如果發送失敗,會繼續重試,直到 Receiver 收到消息爲止,同時保證 Receiver 不會因爲消息重傳而收到重複的消息。
注:
QoS 是 Sender 和 Receiver 之間達成的協議,不是 Publisher 和 Subscriber 之間達成的協議。也就是說 Publisher 發佈一條 QoS1 的消息,只能保證 Broker 能至少收到一次這個消息;至於對應的 Subscriber 能否至少收到一次這個消息,還要取決於 Subscriber 在 Subscribe 的時候和 Broker 協商的 QoS 等級。
Qos0
Sender 向 Receiver 發送一個包含消息數據的 PUBLISH 包,然後不管結果如何,丟棄掉已發送的 PUBLISH 包,一條消息的發送完成。
QoS1
QoS 要保證消息至少到達 Sender 一次,所以有一個應答的機制。
- Sender 向 Receiver 發送一個帶有消息數據的 PUBLISH 包, 並在本地保存這個 PUBLISH 包。
- Receiver 收到 PUBLISH 包以後,向 Sender 發送一個 PUBACK 數據包,PUBACK 數據包沒有消息體(Payload),在可變頭中(Variable header)中有一個包標識(Packet Identifier),和它收到的 PUBLISH 包中的 Packet Identifier 一致。
- Sender 收到 PUBACK 之後,根據 PUBACK 包中的 Packet Identifier 找到本地保存的 PUBLISH 包,然後丟棄掉,一次消息的發送完成。
- 如果 Sender 在一段時間內沒有收到 PUBLISH 包對應的 PUBACK,它將該 PUBLISH 包的 DUP 標識設爲 1(代表是重新發送的 PUBLISH 包),然後重新發送該 PUBLISH 包。重複這個流程,直到收到 PUBACK,然後執行第 3 步。
QoS2
- Sender 發送 QoS 爲 2 的 PUBLISH 數據包,數據包 Packet Identifier 爲 P,並在本地保存該 PUBLISH 包;
- Receiver 收到 PUBLISH 數據包以後,在本地保存 PUBLISH 包的 Packet Identifier P,並回復 Sender 一個 PUBREC 數據包,PUBREC 數據包可變頭中的 Packet Identifier 爲 P,沒有消息體(Payload);
- 當 Sender 收到 PUBREC,它就可以安全地丟棄掉初始的 Packet Identifier 爲 P 的 PUBLISH 數據包,同時保存該 PUBREC 數據包,同時回覆 Receiver 一個 PUBREL 數據包,PUBREL 數據包可變頭中的 Packet Identifier 爲 P,沒有消息體;如果 Sender 在一定時間內沒有收到 PUBREC,它會把 PUBLISH 包的 DUP 標識設爲 1,重新發送該 PUBLISH 數據包(Payload);
- 當 Receiver 收到 PUBREL 數據包,它可以丟棄掉保存的 PUBLISH 包的 Packet Identifier P,並回復 Sender 一個 PUBCOMP 數據包,PUBCOMP 數據包可變頭中的 Packet Identifier 爲 P,沒有消息體(Payload);
- 當 Sender 收到 PUBCOMP 包,那麼它認爲數據包傳輸已完成,它會丟棄掉對應的 PUBREC 包。如果 Sender 在一定時間內沒有收到 PUBCOMP 包,它會重新發送 PUBREL 數據包。
QoS 和會話(Session)
如果 Client 想接收離線消息,必須使用持久化的會話(Clean Session = 0)連接到 Broker,這樣 Broker 纔會存儲 Client 在離線期間沒有確認接收的 QoS 大於 1 的消息。
QoS降級問題
在 MQTT 協議中,從 Broker 到 Subscriber 這段消息傳遞的實際 QoS 等於:Publisher 發佈消息時指定的 QoS 等級和 Subscriber 在訂閱時與 Broker 協商的 QoS 等級,這兩個 QoS 等級中的最小那一個。
QoS選擇
- 在以下情況下你可以選擇 QoS0:
- Client 和 Broker 之間的網絡連接非常穩定,例如一個通過有線網絡連接到 Broker 的測試用 Client;
- 可以接受丟失部分消息,比如你有一個傳感器以非常短的間隔發佈狀態數據,所以丟一些也可以接受;
- 不需要離線消息。
- 在以下情況下你應該選擇 QoS1:
- 你需要接收所有的消息,而且你的應用可以接受並處理重複的消息;
- 你無法接受 QoS2 帶來的額外開銷,QoS1 發送消息的速度比 QoS2 快很多。
- 在以下情況下你應該選擇 QoS2:
- 你的應用必須接收到所有的消息,而且你的應用在重複的消息下無法正常工作,同時你也能接受 QoS2 帶來的額外開銷。