歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~
翻譯人:Tnecesoc,該成員來自雲+社群翻譯社
訊息佇列遙測傳輸(MQTT)是一種客戶端伺服器釋出 / 訂閱訊息傳輸協議。它輕量,開放,簡單,其設計也易於實施。這些特性使其非常適合用於很多情況,包括在網路連線受限的,需要程式碼長度較小且 / 或網路頻寬非常重要的環境裡面,例如在機器對機器(M2M)和物聯網(IoT)環境中的通訊。該協議通過 TCP / IP 或其他能提供有序,無損,雙向的連線的網路協議執行。
MQTT支援三種服務質量級別,如上圖所示:
- 最多傳送一次(發完就忘),也就是不確認
- 至少傳送一次,需要進行確認
- 正好傳送一次,要進行 4 步握手
QoS(服務質量)定義了服務端(Broker) / 客戶端(Client)確保能收到訊息的工作或嘗試的方式。訊息可以以任何 QoS 級別傳送,客戶端也可以選擇以任意 QoS 級別來訂閱主題,後者選擇的是他們能收到的最高 QoS 級別。
例如,如有訊息以 QoS 2 級別釋出並且有一客戶端以 Qos 0 級別訂閱了相應主題,則那一客戶端就會以 QoS 0 級別收到該訊息。如果有第二個客戶端也訂閱了相同的主題,但用的是 QoS 2,則它將以 QoS 2 級別收到這一訊息。
舉另外一個例子,如有一客戶端以 QoS 2 訂閱了一個主題,並且有一訊息以 QoS 0 在相應主題上釋出,則客戶端將會基於 QoS 0 級別接收這一訊息。高階的 QoS 會更可靠,但也會帶來更高的延遲,並佔用更多的頻寬。
每個 QoS 級別的一些細節就如下所示。MQTT 控制資料包內容的表格位於本文的最後部分,用於描述來自每個 QoS 流的控制資料包。
服務質量級別 0
該訊息最多隻傳送一次,或者在通過網路的傳送受阻的時候根本不傳送。傳送的訊息不會被儲存。如果客戶端斷開了連線,或者服務端出現了故障,該訊息可能就會因此丟失。這也是最快的傳輸模式。MQTT 協議並沒有要求伺服器端將 QoS = 0 的釋出訊息轉發給客戶端。如果客戶端在伺服器收到釋出的訊息時斷開了連線,則釋出的訊息可能會被丟棄,具體取決於伺服器。遙測(MQXR)服務不會丟棄以 QoS = 0 傳送的訊息。它們會被作為非持久訊息而儲存,且只有在佇列管理器停止運作時才會被丟棄。
在 QoS 0 傳送協議中:
- 傳送者:必須傳送 QoS = 0,DUP = 0 的 PUBLISH 包;
- 接收者:在接收到 PUBLISH 包的同時也接受訊息的所有權。
服務質量級別 1
該訊息至少傳送一次。如果傳送方沒有收到確認包,則會再次傳送加上 DUP 標誌的該訊息,直到收到確認包為止。因此,接收者可能會把相同的訊息傳送好幾次,並且也可能把它處理了好幾遍。訊息必須儲存在傳送者以及接收者的本地環境裡面,直到這一訊息被妥善處理為止。接收者在處理完訊息後會把訊息刪掉。如果接收者是個服務端,則它會將把該訊息釋出給其訂閱者作為對訊息的處理。如果接收者是客戶端,則會將把訊息傳遞給作為訂閱者的應用程式作為處理。在訊息被刪除之後,接收方會向傳送方傳送確認包。傳送方在收到接收方的確認後會刪掉儲存在傳送方的訊息。
這個級別可以用於傳送例如環境感測器這樣的資料。在這種情況下,單個讀數的傳送失敗了也沒多大關係,因為感測器很快就會再把讀數傳送一遍。
在 QoS 1 傳送協議中:
-
傳送方:
- 必須在每次有新的應用訊息釋出時為其分配一個沒被佔用的包識別符號。
- 必須傳送一個 PUBLISH 包,其中包含 QoS = 1,DUP = 0 的包識別符號。
- 必須將 PUBLISH 資料包視為 “未經確認” 的,直到它收到了接收方發來的,相應的 PUBACK 資料包為止。
- 一旦傳送者收到 PUBACK 包,對應的訊息的包識別符號就能收回並重用。請注意,當傳送方正在等待接收確認時,它可以用不同的包識別符號傳送更多的 PUBLISH 包。
-
接收方:
- 在接受了應用訊息的所有權後,必須用包含傳入 PUBLISH 包的包識別符號的 PUBACK 包來進行響應。
- 在傳送 PUBACK 包後,接收方必須把每一個傳入的包含相同包識別符號 PUBLISH 包視為一個全新的釋出訊息,而不管這些釋出訊息有沒有加上 DUP 標誌。
服務質量級別 2
該訊息始終只傳送一次。訊息必須儲存在傳送方和接收方的本地環境中,直到它被妥善處理為止。QoS = 2 是最安全但也是最慢的傳輸模式。從傳送方刪掉訊息之前,傳送方和接收方之間至少需要兩次相互的傳輸。在第一次傳輸後,接收方就可以開始處理這一訊息。在第一次互傳中,傳送方會傳送訊息並從接收方拿到對這一訊息的確認。如果傳送方沒有收到確認,則會再次傳送加上了 DUP 標誌的該訊息,直至收到確認。在第二次互傳中,傳送方通過給接收方傳送 PUBREL 訊息來告知後者它可以完成對釋出的訊息的處理了。如果傳送方沒有收到接收方對 PUBREL 訊息的確認,則會把 PUBREL 訊息再發一遍,直到收到確認為止。當傳送者收到對 PUBREL 訊息的確認時,傳送者就會刪掉它儲存的訊息。接收者可以在第一或第二次互傳的時候處理訊息,只要它不把訊息又重新處理一遍就可以了。如果接收者是服務端,它會將訊息釋出給訂閱者。如果接收方是客戶端,它會將訊息傳遞給作為訂閱者的應用程式。最後接收方會向傳送方傳送處理完成的訊息,來表明它已完成了訊息的處理。
舉例來說,計費系統可以使用這個級別,因為訊息的重複或丟失會導致這樣的應用產生錯誤的計費。
在 QoS 2 傳送協議中:
-
傳送方:
- 必須在每次有新的應用訊息釋出時為其分配一個沒被佔用的包識別符號。
- 必須傳送一個包含 QoS = 2,DUP = 0 的包識別符號的 PUBLISH 包。
- 必須將 PUBLISH 資料包視為 “未經確認” 的,直到它收到了接收方發來的,相應的 PUBREC 資料包為止。
- 當它從接收器收到一個 PUBREC 包時,必須傳送一個 PUBREL 包。這個 PUBREL 包應該包含與原始 PUBLISH 分組相同的包識別符號。
- 必須將 PUBREL 資料包視為 “未經確認” 的,直到它從接收方收到了相應的 PUBCOMP 包為止。
- 一旦傳送了相應的 PUBREL 包,傳送方就不能再傳送原始的 PUBLISH 包。一旦傳送者收到 PUBCOMP 包,包識別符號就可以收回並重用。注意,當傳送方正在等待接收確認時,它可以使用不同的包識別符號傳送更多的 PUBLISH 包。
-
接收方:
- 在接受了 PUBLISH 包的應用訊息的所有權後,必須用包含傳入 PUBLISH 包的包識別符號的 PUBREC 包來進行響應。
- 在接收方收到相應的 PUBREL 包之前,它必須對每一個具有和傳入 PUBLISH 包相同包識別符號的後續 PUBLISH 包傳送一個 PUBREC 包來進行確認。它絕不能容許把一個內容重複的訊息傳給任何位於下游的接收方。
- 在收到傳送方發來的 PUBREL 包之後,它必須通過傳送包含與 PUBREL 相同的包識別符號的 PUBCOMP 包來響應。
- 傳送 PUBCOMP 包後,接收方必須把任何後續的具有與傳入 PUBLISH 包相同包識別符號的後續 PUBLISH 包視為全新的釋出訊息。
MQTT 控制資料包的詳述
控制包 | 傳送方向 | 描述 |
---|---|---|
CONNECT | 客戶端 -> 服務端 | 客戶端請求與服務端建立連線 |
CONNACK | 服務端 -> 客戶端 | 連線成功建立 |
PUBLISH | 客戶端 -> 服務端 / 服務端 -> 客戶端 | 釋出訊息 |
PUBACK | 客戶端 -> 服務端 / 服務端 -> 客戶端 | 收到釋出訊息的確認 |
PUBREC | 客戶端 -> 服務端 / 服務端 -> 客戶端 | 收到釋出訊息(Qos 2 的第二次握手) |
PUBREL | 客戶端 -> 服務端 / 服務端 -> 客戶端 | 不再發布訊息(Qos 2 的第三次握手) |
PUBCOMP | 客戶端 -> 服務端 / 服務端 -> 客戶端 | 訊息釋出的完結(Qos 2 的第四次握手) |
SUBSCRIBE | 客戶端 -> 服務端 | 客戶端請求訂閱某主題 |
SUBACK | 服務端 -> 客戶端 | 訂閱操作成功 |
UNSCBSCRIBE | 客戶端 -> 服務端 | 客戶端請求取消訂閱某主題 |
UNSCBACK | 服務端 -> 客戶端 | 取消訂閱操作成功 |
PINGREQ | 客戶端 -> 服務端 | PING 請求 |
PINGRESP | 服務端 -> 客戶端 | PING 響應 |
DISCONNECT | 客戶端 -> 服務端 | 客戶端斷開了與服務端的連線 |
參考文獻
OASIS 文件:
有些內容轉自 BB Smartworx 和 IBM Developer Work。
本文的版權歸 Tnecesoc 所有,如需轉載請聯絡作者。
問答
相關閱讀