4.3 Quality of Service levels and protocol flows 服務質量水平和協議流程
MQTT根據此處定義的服務質量(QoS)級別提供應用程序消息。傳遞協議是對稱的,在下面的描述中,客戶端和服務器都可以扮演發送者或接收者的角色。傳遞協議僅涉及從單個發送方向單個接收方傳遞應用程序消息。當服務器向多個客戶端提供應用程序消息時,將獨立處理每個客戶端。用於向客戶端傳送出站的應用程序消息的QoS級別可能與入站應用程序消息的QoS級別不同。
以下部分中的非規範流程圖旨在顯示可能的實現方法。
4.3.1 QoS 0:At most once delivery 最多一次交付
根據底層網絡的功能傳遞消息。接收方未發送響應,發送方不執行重試。消息一次到達接收器或根本不到達接收器。
在QoS 0傳遞協議中,發送者
·必須發送QoS = 0,DUP = 0 [MQTT-4.3.1-1] 的PUBLISH數據包。
在QoS 0傳送協議中,接收器
·接收PUBLISH數據包時接受消息的所有權。
發件人行動 |
控制包 |
接收者行動 |
發佈QoS 0,DUP = 0
|
|
|
|
----------> |
|
|
|
向適當的轉發收件人發送應用程序消息 |
4.3.2 QoS 1:At least once delivery 至少一次交付
這種服務質量確保消息至少到達接收器一次。QoS 1 PUBLISH分組在其可變報頭中具有分組標識符,並由PUBACK分組確認。第2.3.1節提供了有關數據包標識符的更多信息。
在QoS 1傳遞協議中,發送者
·每次要發佈新的應用程序消息時,必須分配一個未使用的數據包標識符。
·必須發送包含此數據包標識符的PUBLISH數據包,其QoS = 1,DUP = 0。
·必須將PUBLISH數據包視爲“未確認”,直到它從接收方收到相應的PUBACK數據包。有關未確認消息的討論,請參見第4.4 節。
[MQTT-4.3.2-1]。
一旦發送方收到PUBACK數據包,數據包標識符就可以重用。
請注意,允許發件人在等待接收確認時發送具有不同數據包標識符的其他PUBLISH數據包。
在QoS 1傳送協議中,接收器
- 必須使用包含來自傳入的PUBLISH數據包的數據包標識符的PUBACK數據包進行響應,並接受應用程序消息的所有權
- 在發送PUBACK數據包之後,接收方必須將包含相同數據包標識符的任何傳入PUBLISH數據包視爲新發布,而不管其DUP標誌的設置如何。
[MQTT-4.3.2-2]。
發件人行動 |
控制包 |
接收者行動 |
存儲消息 |
|
|
發送PUBLISH QoS 1,DUP 0, |
----------> |
|
|
|
啓動應用程序消息1的繼續交付 |
|
<---------- |
發送PUBACK <數據包標識符> |
丟棄消息 |
|
|
1在發送PUBACK之前,接收方無需完成應用程序消息的傳遞。當其原始發送方收到PUBACK數據包時,應用程序消息的所有權將傳輸到接收方。
4.3.3 QoS 2: Exactly once delivery 確保一次交付
這是最高質量的服務,用於既不接受丟失也不重複消息的情況。與此服務質量相關的開銷增加。
QoS 2消息在其變量頭中具有分組標識符。第2.3.1節提供了有關數據包標識符的更多信息。QoS 2 PUBLISH數據包的接收方通過兩步確認過程確認收到。
在QoS 2傳遞協議中,發送者
- 當有新的應用程序消息要發佈時,必須分配一個未使用的數據包標識符。
- 必須發送包含此數據包標識符的PUBLISH數據包,其QoS = 2,DUP = 0。
- 必須將PUBLISH數據包視爲“未確認”,直到它從接收方收到相應的PUBREC數據包。有關未確認消息的討論,請參見第4.4 節。
- 必須在從接收器接收PUBREC數據包時發送PUBREL數據包。該PUBREL分組必須包含與原始PUBLISH分組相同的分組標識符。
- 必須將PUBREL數據包視爲“未確認”,直到它從接收方收到相應的PUBCOMP數據包。
- 一旦發送了相應的PUBREL數據包,就不能重新發送PUBLISH。
[MQTT-4.3.3-1]。
一旦發件人收到PUBCOMP數據包,數據包標識符就可以重用了。
請注意,允許發件人在等待接收確認時發送具有不同數據包標識符的其他PUBLISH數據包。
在QoS 2傳送協議中,接收器
- 必須使用包含來自PUBLISH數據包的數據包標識符的PUBREC進行響應,並接受應用程序消息的所有權。
- 在收到相應的PUBREL數據包之前,接收方必須通過發送PUBREC來確認具有相同數據包標識符的任何後續PUBLISH數據包。在這種情況下,它不得導致重複的郵件傳遞給任何轉發收件人。
- 必須通過發送包含與PUBREL相同的包標識符的PUBCOMP包來響應PUBREL包。
- 在發送了PUBCOMP之後,接收方必須將包含該數據包標識符的任何後續PUBLISH數據包視爲新發布。
[MQTT-4.3.3-2]
發件人行動 |
控制包 |
接收者行動 |
存儲消息 |
|
|
PUBLISH QoS 2,DUP 0 |
|
|
|
----------> |
|
|
|
方法A,存儲消息 |
|
|
PUBREC <數據包標識符> |
|
<---------- |
|
丟棄消息,Store PUBREC收到<Packet Identifier> |
|
|
PUBREL <數據包標識符> |
|
|
|
----------> |
|
|
|
方法A,啓動應用程序消息1的繼續傳遞, 然後丟棄消息 |
|
|
發送PUBCOMP <數據包標識符> |
|
<---------- |
|
丟棄存儲狀態 |
|
|
1在發送PUBREC或PUBCOMP之前,接收方無需完成應用程序消息的傳送。當其原始發送方接收到PUBREC數據包時,應用程序消息的所有權將傳輸到接收方。
圖4.3 顯示接收器可以通過兩種方法處理QoS 2。它們在消息可用於向前傳遞的流程中的不同點。方法A或方法B的選擇是特定於實現的。只要實現選擇這些方法中的一種,這不會影響QoS 2流的保證。
4.4 Message delivery retry 消息傳遞重試
當客戶端重新連接CleanSession設置爲0時,客戶端和服務器必須使用其原始數據包標識符 [MQTT-4.4.0-1] 重新發送任何未確認的PUBLISH數據包(其中QoS> 0)和PUBREL數據包。 這是客戶端或服務器需要重新傳遞消息的唯一情況。
非規範性註釋
歷史上需要重新傳輸控制數據包以克服某些舊TCP網絡上的數據丟失。對於要在此類環境中部署MQTT 3.1.1實現的問題,這可能仍然是一個問題。
4.5 Message receipt 留言收據
當服務器獲取傳入的應用程序消息的所有權時,它必須將其添加到具有匹配的訂閱的那些客戶端的會話狀態。匹配規則在第4.7 節[MQTT-4.5.0-1] 中定義。
在正常情況下,客戶端會收到消息以響應他們創建的訂閱。客戶端還可以接收與其任何顯式訂閱都不匹配的消息。如果服務器自動爲客戶端分配了訂閱,則會發生這種情況。在UNSUBSCRIBE操作正在進行時,客戶端也可以接收消息。客戶端必須根據適用的QoS規則確認它收到的任何發佈數據包,無論它是否選擇處理它包含的應用程序消息 [MQTT-4.5.0-2]。
4.6 Message ordering 消息排序
在實現本章其他地方定義的協議流時,客戶端必須遵循這些規則:
- 當它重新發送任何PUBLISH數據包時,它必須按發送原始PUBLISH數據包的順序重新發送它們(這適用於QoS 1和QoS 2消息) [MQTT-4.6.0-1]
- 它必須按照接收相應PUBLISH數據包的順序發送PUBACK數據包(QoS 1消息) [MQTT-4.6.0-2]
- 它必須按照接收相應PUBLISH數據包的順序發送PUBREC數據包(QoS 2消息) [MQTT-4.6.0-3]
- 它必須按照接收相應PUBREC數據包的順序發送PUBREL數據包(QoS 2消息) [MQTT-4.6.0-4]
默認情況下,服務器必須將每個主題視爲“有序主題”。它可以提供管理或其他機制,允許將一個或多個主題視爲“無序主題” [MQTT-4.6.0-5]。
當服務器處理已發佈到有序主題的消息時,它必須在向每個訂戶發送消息時遵循上面列出的規則。此外,它必須按照從任何給定客戶端 [MQTT-4.6.0-6] 收到的順序向用戶發送PUBLISH數據包(對於相同的主題和QoS)。
非規範性評論
上面列出的規則確保在發佈消息流並使用QoS 1訂閱時,訂閱者收到的每條消息的最終副本將按照它們最初發布的順序排列,但可能會導致消息重複的可能性重新發送在其後續消息之一後收到的早期消息。例如,發佈者可以按1,2,3,4的順序發送消息,訂閱者可以按1,2,3,2,3,4的順序接收消息。
如果客戶端和服務器都確保在任何時間只有一個消息“在飛行中”(通過在其前任已被確認之前不發送消息),那麼在任何後續消息之後將不會收到任何QoS消息 - 例如,訂戶可能按順序1,2,3,3,4但不是1,2,3,2,3,4接收它們。將飛行中窗口設置爲1還意味着即使發佈者在同一主題上發送具有不同QoS等級的消息序列,也將保留訂單。