MQTT系列-MQTT的QoS介紹

1. MQTT中的QoS等級(jí)

MQTT設(shè)計(jì)了一套保證消息穩(wěn)定傳輸?shù)臋C(jī)制扇调,包括消息應(yīng)答、存儲(chǔ)和重傳。
為了保證消息被正確的接收
在這套機(jī)制下蟀伸,提供了三種不同層次QoS(Quality of Service):

  • QoS0,At most once缅刽,至多一次啊掏;
  • QoS1,At least once衰猛,至少一次迟蜜;
  • QoS2,Exactly once啡省,確保只有一次娜睛。

QoS 是消息的發(fā)送方(Sender)和接受方(Receiver)之間達(dá)成的一個(gè)協(xié)議:

  • QoS0 代表髓霞,Sender 發(fā)送的一條消息,Receiver 最多能收到一次微姊,也就是說(shuō) Sender 盡力向 Receiver 發(fā)送消息酸茴,如果發(fā)送失敗,也就算了兢交;
  • QoS1 代表薪捍,Sender 發(fā)送的一條消息,Receiver 至少能收到一次配喳,也就是說(shuō) Sender 向 Receiver 發(fā)送消息酪穿,如果發(fā)送失敗,會(huì)繼續(xù)重試晴裹,直到 Receiver 收到消息為止被济,但是因?yàn)橹貍鞯脑颍琑eceiver 有可能會(huì)收到重復(fù)的消息涧团;
  • QoS2 代表只磷,Sender 發(fā)送的一條消息,Receiver 確保能收到而且只收到一次泌绣,也就是說(shuō) Sender 盡力向 Receiver 發(fā)送消息钮追,如果發(fā)送失敗,會(huì)繼續(xù)重試阿迈,直到 Receiver 收到消息為止元媚,同時(shí)保證 Receiver 不會(huì)因?yàn)橄⒅貍鞫盏街貜?fù)的消息。

::: warning
QoS是Sender和Receiver之間的協(xié)議苗沧,而不是Publisher和Subscriber之間的協(xié)議刊棕。
換句話(huà)說(shuō),Publisher發(fā)布了一條QoS1的消息待逞,只能保證Broker能至少收到一次這個(gè)消息甥角;

而對(duì)于Subscriber能否至少收到一次這個(gè)消息,還要取決于Subscriber在Subscribe的時(shí)候和Broker協(xié)商的QoS等級(jí)识樱。
:::

1.1. QoS0

QoS0等級(jí)下蜈膨,Sender和Receiver之間一次消息的傳遞流程如下:

image

Sender向Receiver發(fā)送一個(gè)包含消息數(shù)據(jù)的PUBLISH包,然后不管結(jié)果如何牺荠,丟掉已發(fā)送的PUBLISH包,一條消息的發(fā)送完成驴一。

1.2. QoS1

QoS1要保證消息至少到達(dá)一次休雌,所以有一個(gè)應(yīng)答的機(jī)制。Sender和Receiver的一次消息的傳遞流程如下:

image

1.Sender向Receiver發(fā)送一個(gè)帶有數(shù)據(jù)的PUBLISH包肝断,并在本地保存這個(gè)PUBLISH包杈曲;
2.Receiver收到PUBLISH包以后驰凛,向Sender發(fā)送一個(gè)PUBACK數(shù)據(jù)包,PUBACK數(shù)據(jù)包沒(méi)有消息體(Payload)担扑,在可變頭中有一個(gè)包標(biāo)識(shí)(Packet Identifier)恰响,和它收到的PUBLISH包中的Packet Identifier一致。
3.Sender收到PUBACK之后涌献,根據(jù)PUBACK包中的Packet Identifier找到本地保存的PUBLISH包胚宦,然后丟棄掉,一次消息的發(fā)送完成燕垃。

但是消息傳遞流程中可能會(huì)出現(xiàn)問(wèn)題:

  • 如果Sender在一段時(shí)間內(nèi)沒(méi)有收到PUBLISH包對(duì)應(yīng)的PUBACK枢劝,它將該P(yáng)UBLISH包的DUP標(biāo)識(shí)設(shè)為1(代表是重新發(fā)送的PUBLISH包),然后重新發(fā)送該P(yáng)UBLISH包卜壕。
  • Receiver可能會(huì)重復(fù)收到消息您旁,需自行去重。

1.3. QoS2

相比QoS0和QoS1,QoS2不僅要確保Receiver能收到Sender發(fā)送的消息轴捎,還需要確保消息不重復(fù)鹤盒。它的重傳和應(yīng)答機(jī)制就要復(fù)雜一些,同時(shí)開(kāi)銷(xiāo)也是最大的侦副。QoS2下侦锯,一次消息的傳遞流程如下所示:

image

1.Sender發(fā)送QoS為2的PUBLISH數(shù)據(jù)包,數(shù)據(jù)包 Packet Identifier 為 P跃洛,并在本地保存該P(yáng)UBLISH包率触;

2.Receiver收到PUBLISH數(shù)據(jù)包后,在本地保存PUBLISH包的Packet Identifier P汇竭,并回復(fù)Sender一個(gè)PUBREC數(shù)據(jù)包葱蝗,PUBREC數(shù)據(jù)包可變頭中的Packet Identifier為P,沒(méi)有消息體(Payload)细燎;

3.當(dāng)Sender收到PUBREC两曼,它就可以安全的丟棄掉初始Packet Identifier為P的PUBLISH數(shù)據(jù)包。同時(shí)保存該P(yáng)UBREC數(shù)據(jù)包玻驻,并回復(fù)Receiver一個(gè)PUBREL數(shù)據(jù)包悼凑,PUBREL數(shù)據(jù)包可變頭中的Packet Identifier為P,沒(méi)有消息體璧瞬;

4.當(dāng)Receiver收到PUBREL數(shù)據(jù)包户辫,它可以丟掉保存的PUBLISH包的Packet Identifier P,并回復(fù)Sender一個(gè)可變頭中 Packet Identifier 為 P嗤锉,沒(méi)有消息體(Payload)的PUBCOMP數(shù)據(jù)包渔欢;

5.當(dāng)Sender收到PUBCOMP包,那么認(rèn)為傳輸已完成瘟忱,則丟掉對(duì)應(yīng)的PUBREC數(shù)據(jù)包奥额;

上面是一次完整無(wú)誤的傳輸過(guò)程苫幢,然而傳輸過(guò)程中可能會(huì)出現(xiàn)以下情況:

  • 情況1:Sender發(fā)送PUBLISH數(shù)據(jù)包給Receiver的時(shí)候,發(fā)送失數姘ぁ韩肝;
  • 情況2:Sender已經(jīng)成功發(fā)送PUBLISH數(shù)據(jù)包給Receiver了,但是Receiver發(fā)送PUBREC數(shù)據(jù)包失斁爬啤哀峻;
  • 情況3:Sender已經(jīng)成功收到了PUBREC數(shù)據(jù)包,但是PUBREL數(shù)據(jù)包發(fā)送失斨闾搿谜诫;
  • 情況4:Receiver已經(jīng)收到了PUBREL數(shù)據(jù)包,但是發(fā)送PUBCOMP數(shù)據(jù)包時(shí)發(fā)送失敗

針對(duì)上述的問(wèn)題攻旦,較為詳細(xì)的處理方法如下:

  • 不管是情況1還是情況2喻旷,因?yàn)镾ender在一定時(shí)間內(nèi)沒(méi)有收到PUBREC,那么它會(huì)把PUBLISH包的DUP標(biāo)識(shí)設(shè)為1牢屋,重新發(fā)送該P(yáng)UBLISH數(shù)據(jù)包且预;

  • 不管是情況3還是情況4,因?yàn)镾ender在一定時(shí)間內(nèi)沒(méi)有收到PUBCOMP包烙无,那么它會(huì)重新發(fā)送PUBREL數(shù)據(jù)包锋谐;

  • 針對(duì)情況2,Receiver可能會(huì)收到多個(gè)重復(fù)的PUBLISH包截酷,更加完善的處理如下:

  • Receiver在收到PUBLISH數(shù)據(jù)包之后涮拗,馬上回復(fù)一個(gè)PUBREC數(shù)據(jù)包。并會(huì)在本地保存PUBLISH包的Packet Identifier P迂苛,不管之后因?yàn)橹貍鞫嗌俅芜@個(gè)Packet Identifier 為P的數(shù)據(jù)包三热,Receiver都認(rèn)為是重復(fù)的,丟棄三幻。同時(shí)Receiver接收到QoS為2的PUBLISH數(shù)據(jù)包后就漾,并不馬上投遞給上層,而是在本地做持久化念搬,將消息保存起來(lái)(這里需要是持久化而不是保存在內(nèi)存)抑堡。

  • 針對(duì)情況4,更加完善的處理如下:

Receiver收到PUBREL數(shù)據(jù)包后朗徊,正式將消息遞交給上層應(yīng)用層首妖,投遞之后銷(xiāo)毀Packet Identifier P,并發(fā)送PUBCOMP數(shù)據(jù)包爷恳,銷(xiāo)毀之前的持久化消息悯搔。
之后不管接收到多少個(gè)PUBREL數(shù)據(jù)包,因?yàn)闆](méi)有Packet Identifier P,直接回復(fù)PUBCOMP數(shù)據(jù)包即可妒貌。

2. QoS降級(jí)

在 MQTT 協(xié)議中,從 Broker 到 Subscriber 這段消息傳遞的實(shí)際 QoS 等于:Publisher 發(fā)布消息時(shí)指定的 QoS 等級(jí)和 Subscriber 在訂閱時(shí)與 Broker 協(xié)商的 QoS 等級(jí)铸豁,這兩個(gè) QoS 等級(jí)中的最小那一個(gè)灌曙。

Actual Subscribe QoS = MIN(Publish QoS, Subscribe QoS)

3. QoS和會(huì)話(huà)

如果 Client 想接收離線(xiàn)消息,必須使用持久化的會(huì)話(huà)(Clean Session = 0)連接到 Broker节芥,這樣 Broker 才會(huì)存儲(chǔ) Client 在離線(xiàn)期間沒(méi)有確認(rèn)接收的 QoS 大于 等于1 的消息在刺。

在發(fā)送QoS為1或2的情況,Broker(此時(shí)為Sender)會(huì)將發(fā)送的PUBLISH數(shù)據(jù)包保存到本地头镊,直到收到一系列回復(fù)的數(shù)據(jù)包蚣驼,
然而Client(此時(shí)為Receiver)在離線(xiàn)期間無(wú)法回復(fù)相應(yīng)的數(shù)據(jù)包,所以會(huì)一直存儲(chǔ)相艇。

4. QoS等級(jí)使用建議

在以下情況下你可以選擇 QoS0:

  • Client 和 Broker 之間的網(wǎng)絡(luò)連接非常穩(wěn)定颖杏,例如一個(gè)通過(guò)有線(xiàn)網(wǎng)絡(luò)連接到 Broker 的測(cè)試用 Client;
  • 可以接受丟失部分消息坛芽,比如你有一個(gè)傳感器以非常短的間隔發(fā)布狀態(tài)數(shù)據(jù)留储,所以丟一些也可以接受;
  • 你不需要離線(xiàn)消息咙轩。

在以下情況下你應(yīng)該選擇 QoS1:

  • 你需要接收所有的消息获讳,而且你的應(yīng)用可以接受并處理重復(fù)的消息;
  • 你無(wú)法接受 QoS2 帶來(lái)的額外開(kāi)銷(xiāo)活喊,QoS1 發(fā)送消息的速度比 QoS2 快很多丐膝。

在以下情況下你應(yīng)該選擇 QoS2:

  • 你的應(yīng)用必須接收到所有的消息,而且你的應(yīng)用在重復(fù)的消息下無(wú)法正常工作钾菊,同時(shí)你也能接受 QoS2 帶來(lái)的額外開(kāi)銷(xiāo)帅矗。

參考

https://blog.csdn.net/programguo/article/details/100125177

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市结缚,隨后出現(xiàn)的幾起案子损晤,更是在濱河造成了極大的恐慌,老刑警劉巖红竭,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尤勋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡茵宪,警方通過(guò)查閱死者的電腦和手機(jī)最冰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稀火,“玉大人暖哨,你說(shuō)我怎么就攤上這事』四” “怎么了篇裁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵沛慢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我达布,道長(zhǎng)团甲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任黍聂,我火速辦了婚禮躺苦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘产还。我一直安慰自己匹厘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布脐区。 她就那樣靜靜地躺著愈诚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坡椒。 梳的紋絲不亂的頭發(fā)上扰路,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音倔叼,去河邊找鬼汗唱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丈攒,可吹牛的內(nèi)容都是我干的哩罪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼巡验,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼际插!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起显设,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤框弛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后捕捂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瑟枫,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年指攒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了慷妙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡允悦,死狀恐怖膝擂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤架馋,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布狞山,位于F島的核電站,受9級(jí)特大地震影響叉寂,放射性物質(zhì)發(fā)生泄漏铣墨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一办绝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姚淆,春花似錦孕蝉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至搏讶,卻和暖如春佳鳖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背媒惕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工系吩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人妒蔚。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓穿挨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親肴盏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子科盛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容