文章目錄
- 什麼是服務品質?
- QoS = 0 – 最多發一次
- QoS = 1 – 最少發一次
- QoS = 2 – 保證收一次
- 設定QoS
- 服務品質降級
- QoS=1通訊時的注意事項
- QoS=2通訊時的注意事項
- 小結
什麼是服務品質?
在之前的課程裡我們提到過,一個物聯網系統中有些資訊非常重要,我們需要確定這類重要資訊可以準确無誤的發送和接收,而有些資訊則相對不那麼重要,這類資訊如果在傳輸中丢失不會影響系統的運作。
MQTT服務品質(Quality of Service 縮寫 QoS)正是用于告知物聯網系統,哪些資訊是重要資訊需要準确無誤的傳輸,而哪些資訊不那麼重要,即使丢失也沒有問題。
MQTT協定有三種服務品質級别:
QoS = 0 – 最多發一次
QoS = 1 – 最少發一次
QoS = 2 – 保證收一次
以上三種不同的服務品質級别意味着不同的MQTT傳輸流程。對于較為重要的MQTT消息,我們通常會選擇QoS>0的服務級别(即QoS 為1或2)。
另外這裡提到的“發”與“收”有兩種可能。一種是用戶端釋出消息時,将消息發送給服務端。一種是用戶端訂閱了某一主題消息後,服務端将消息發送給用戶端。是以釋出消息和接收消息的可能是服務端也可能是用戶端。
為了避免為您造成混淆,我們在本節教程後面的描述中将使用“發送端”來描述發送MQTT消息的裝置,而使用“接收端”來描述接收MQTT消息的裝置。
接下來我們仔細看一下這三種服務品質級别的具體含義。
QoS = 0 – 最多發一次
0是服務品質QoS的最低級别。當QoS為0級時,MQTT協定并不保證所有資訊都能得以傳輸。也就是說,QoS=0的情況下,MQTT服務端和用戶端不會對消息傳輸是否成功進行确認和檢查。消息能否成功傳輸全看網絡環境是否穩定。
也就是說,在QoS為0時。發送端一旦發送完消息後,就完成任務了。發送端不會檢查發出的消息能否被正确接收到。
在網絡環境穩定的情況下,資訊傳輸一般是不會出現問題的。但是在環境不穩定的情況下,可能會在傳輸過程中出現MQTT消息丢失的情況。
QoS = 1 – 最少發一次
當QoS級别為1時,發送端在消息發送完成後,會檢查接收端是否已經成功接收到了消息。但是發送端是如何實作這一檢查的呢?請看下圖:
發送端将消息發送給接收端後,會等待接收端的确認。接收端成功接收消息後,會發送一條确認封包PUBACK給發送端。如果發送端收到了這條PUBACK确認封包,那麼它就知道消息已經成功接收。
假如過了一段時間後,發送端沒有收到PUBACK封包,那麼發送端會再次發送消息,然後再次等待接收端的PUBACK确認封包。是以,當QoS=1時,發送端在沒有收到接收端的PUBACK确認封包以前,會重複發送同一條消息。
是以QoS = 1時,每一條消息都至少傳輸一次。
另外請您回憶一下PUBLISH封包的内容。
當發送端重複發送一條消息時,PUBLISH封包中的dupFlag會被設定為True(如上圖黑色橫線所标注的部分)。這是為了告訴接收端,此消息為重複發送的消息。
QoS = 2 – 保證收一次
MQTT服務品質最進階是2級,即QoS = 2。當MQTT服務品質為2級時,MQTT協定可以確定接收端隻接收一次消息。
如下圖所示,QoS=2的收發相對更加複雜。發送端需要接收端進行兩次消息确認。是以,2級MQTT服務品質是最安全的服務級别,也是最慢的服務級别。
下面我們來分步看一下Q0S=2時的消息發送和接收基本流程。
接收端收到QoS為2的消息後,會傳回PUBREC封包作為應答。
發送端收到PUBREC封包後,會把此封包進行存儲,并且傳回PUBREL封包作為應答。
當接收端收到PUBREL封包後,會應答發送端一條PUBCOMP封包。至此,一次QoS2的MQTT消息傳輸就結束了。
以上是QoS=2時的MQTT通訊基本過程。這裡我們隻給您列出了基本流程,而沒有過多的講解MQTT協定是如何控制接收端隻接收一次消息。這麼做是因為本教程的重點是MQTT應用。關于QoS=2的MQTT服務端内部控制機制,我們在實際開發MQTT物聯網的過程中是不會涉及到的。
是以您隻需要牢記一點,那就是QoS=2可以保證接收端隻收一次消息。
設定QoS
了解了QoS的含義後,我們該如何在MQTT通訊中設定QoS呢?下面我們來分别講解用戶端在釋出消息和訂閱消息時如何設定QoS。
釋出消息
如下圖所示,用戶端釋出資訊時,PUBLISH資料包中專有一個資訊為qos。該資訊正是用于設定用戶端釋出MQTT消息的QoS等級。
訂閱消息
同樣的,在用戶端訂閱MQTT主題時,SUBSCRIBE資料包中也同樣有一個資訊用于設定訂閱主題的QoS級别。用戶端正是通過該主題來設定訂閱主題的QoS級别的。
換句話說,無論是釋出(PUBLISH)還是訂閱(SUBSCRIBE),都可以使用資料包中的qos消息設定服務品質級别。
接收端連接配接服務端
另外,要想實作QoS>0的MQTT通訊,用戶端在連接配接服務端時必須要将cleanSession設定為false。如果這一步沒有實作,那麼用戶端是無法實作QoS>0的MQTT通訊。這一點非常關鍵,請您務必要留意。
服務品質降級
講到這裡,不知道有沒有朋友會感到好奇。假如用戶端在釋出和訂閱資訊時使用不同級别的QoS,将會發生什麼情況呢。如下圖所示,假如用戶端A釋出到主題1的消息是采用QoS = 2,然而用戶端B訂閱主題1采用QoS = 1。那麼服務端該如何來應對這一情況呢?
在這種情況下,服務端會使用較低級别來提供服務。如下圖所示,雖然A發送到主題1的消息采用QoS為2,但是服務端發送主題1的消息給B時,采用的QoS為1。這是因為B在訂閱主題1時采用的QoS為1。
下面我們再來看一種情況。
如下圖所示,假如用戶端A釋出主題1消息時使用QoS為0,而用戶端B訂閱主題1消息時使用QoS為1。
在這種情況下,雖然用戶端B訂閱主題1消息時QoS為1,但是由于用戶端A發送主題1消息時QoS為0,是以服務端發送消息給B的QoS為0。
通過以上兩個示例我們可以看到。對于釋出和訂閱消息的用戶端,服務端會主動采用較低級别的QoS來實作消息傳輸。
QoS=1通訊時的注意事項
如想在MQTT通訊中實作服務品質等級為1級(QoS=1),我們要分别對消息的釋出端課接收端進行相應的設定。以下清單中的内容是具體需要采取的措施。
接收端連接配接服務端時cleanSession設定為false
接收端訂閱主題時QoS=1
釋出端釋出消息時QoS=1
QoS=2通訊時的注意事項
小結
- 若想實作QoS>0,訂閱端連接配接服務端時cleanSession需要設定為false,訂閱端訂閱主題時QoS>0,釋出端釋出消息時的QoS>0。
- 服務端會選擇釋出消息和訂閱消息中較低的QoS來實作消息傳輸,這也被稱作“服務降級”。
- QoS = 0, 占用的網絡資源最低,但是接收端可能會出現無法接收消息的情況,是以适用于傳輸重要性較低的資訊。
- QoS = 1, MQTT會確定接收端能夠接收到消息,但是有可能出現接收端反複接收同一消息的情況。
- QoS = 2, MQTT會確定接收端隻接收到一次消息。但是QoS為2時消息傳輸最慢,另外消息傳輸需要多次确認,是以所占用的網絡資源也是最多的。此類服務等級适用于重要消息傳輸。
- 由于QoS1和QoS2都能確定用戶端接收到消息,但是QoS1所占用的資源較QoS2占用資源更小。是以建議使用QoS1來實作網絡資源較為珍貴的環境下傳輸重要資訊。