MQTT協(xié)議之消息處理流程

前言

前面的筆記已把所有消息類型都過了一遍宝与,這里從消息處理流程的角度嘗試解讀一下。

網(wǎng)絡(luò)故障

在任何網(wǎng)絡(luò)環(huán)境下冶匹,都會(huì)出現(xiàn)一方連接失敗习劫,比如離開公司大門那一刻沒有了WIFI信號(hào)。但持續(xù)連接的另一端-服務(wù)器可能不能立即知道對(duì)方已斷開嚼隘。類似網(wǎng)絡(luò)異常情況诽里,都有可能在消息發(fā)送的過程中出現(xiàn),消息發(fā)送出去飞蛹,就丟失了谤狡。
  MQTT協(xié)議假定客戶端和服務(wù)器端穩(wěn)定情況一般,彼此之通信管道不可靠卧檐,一旦客戶端網(wǎng)絡(luò)斷開墓懂,情況就會(huì)很嚴(yán)重,很難恢復(fù)原狀霉囚。
  但別忘記捕仔,很多客戶端會(huì)有永久性存儲(chǔ)設(shè)備支持,比如閃存ROM盈罐、存儲(chǔ)卡等榜跌,在通信出現(xiàn)異常的情況下可以用于保存關(guān)鍵數(shù)據(jù)或狀態(tài)信息等。
  總之盅粪,異常網(wǎng)絡(luò)情況很復(fù)雜钓葫,只能小心處理之。

消息重發(fā)策略

QoS > 0情況下湾揽,PUBLISH瓤逼、PUBREL、SUBSCRIBE库物、UNSUBSCRIBE等類型消息在發(fā)送者發(fā)送完之后霸旗,需要等待一個(gè)響應(yīng)消息,若在一個(gè)指定時(shí)間段內(nèi)沒有收到戚揭,發(fā)送者可能需要重試诱告。重發(fā)的消息,要求DUP標(biāo)記要設(shè)置為1.
  等待響應(yīng)的超時(shí)應(yīng)該在消息成功發(fā)送之后開始算起民晒,并且等待超時(shí)應(yīng)該是可以配置選項(xiàng)精居,以便在下一次重試的時(shí)候锄禽,適當(dāng)加大。比如第一次重試超時(shí)10秒靴姿,下一次可能為20秒沃但,再一次重試可能為60秒呢。當(dāng)然佛吓,還要有一個(gè)重試次數(shù)限制的宵晚。
  還有一種情況,客戶端重新連接维雇,但未在可變頭部中設(shè)置clean session標(biāo)記淤刃,但雙方(客戶端和服務(wù)器端)都應(yīng)該重試先前未發(fā)送的動(dòng)態(tài)消息(in-flight messages)≈ㄐ停客戶端不被強(qiáng)制要求發(fā)送未被確認(rèn)的消息逸贾,但服務(wù)器端就得需要重發(fā)那些未被去確認(rèn)的消息。

QoS level決定的消息處理流程

QoS level為Quality of Service level的縮寫津滞,翻譯成中文铝侵,服務(wù)質(zhì)量等級(jí)。
  MQTT 3.1協(xié)議在"4.1 Quality of Service levels and flows"章節(jié)中据沈,僅僅討論了客戶端到服務(wù)器的發(fā)布流程哟沫,不太完整。因?yàn)闆Q定消息到達(dá)率锌介,能夠提升發(fā)送質(zhì)量的嗜诀,應(yīng)該是服務(wù)器發(fā)布PUBLISH消息到訂閱者這一消息流方向。

QoS level 0

至多發(fā)送一次孔祸,發(fā)送即丟棄隆敢。沒有確認(rèn)消息,也不知道對(duì)方是否收到崔慧。

| Client | Message and direction | Server |
| ------------- |:-------------:|: -----|
| QoS = 0 | PUBLISH
----------> | Action: Publish message to subscribers then Forget
**Reception: **<=1 |

  • 針對(duì)的消息不重要拂蝎,丟失也無所謂。
  • 網(wǎng)絡(luò)層面惶室,傳輸壓力小温自。

QoS level 1

所有QoS level 1都要在可變頭部中附加一個(gè)16位的消息ID
  SUBSCRIBE和UNSUBSCRIBE消息使用QoS level 1皇钞。
  針對(duì)消息的發(fā)布悼泌,Qos level 1,意味著消息至少被傳輸一次夹界。
發(fā)送者若在一段時(shí)間內(nèi)接收不到PUBACK消息馆里,發(fā)送者需要打開DUB標(biāo)記為1,然后重新發(fā)送PUBLISH消息。因此會(huì)導(dǎo)致接收方可能會(huì)收到兩次PUBLISH消息鸠踪。針對(duì)客戶端發(fā)布消息到服務(wù)器的消息處理流程:

| Client | Message and direction | Server |
| ------------- |:-------------:|: ----------|
| QoS = 1
DUP = 0
Message ID = x

Action: Store message | PUBLISH
----------> | Actions:
1. Store message
2. Publish message to subscribers
3. Delete message
**Reception: **>=1 |
| Action: Discard message| PUBACK
<---------- | Message ID = x |
針對(duì)服務(wù)器發(fā)布到訂閱者的消息處理流程:

| Server | Message and direction | Subscriber |
| ------------- |:-------------:|: ----------|
| QoS = 1
DUP = 0
Message ID = x
| PUBLISH
----------> | Actions:
1. Store message
2. Make message available
**Reception: **>=1 |
| | PUBACK
<---------- | Message ID = x |

發(fā)布者(客戶端/服務(wù)器)若因種種異常接收不到PUBACK消息丙者,會(huì)再次重新發(fā)送PUBLISH消息,同時(shí)設(shè)置DUP標(biāo)記為1营密。接收者以服務(wù)器為例械媒,這可能會(huì)導(dǎo)致服務(wù)器收到重復(fù)消息,按照流程卵贱,broker(服務(wù)器)發(fā)布消息到訂閱者(會(huì)導(dǎo)致訂閱者接收到重復(fù)消息)滥沫,然后發(fā)送一條PUBACK確認(rèn)消息到發(fā)布者。
  在業(yè)務(wù)層面键俱,或許可以彌補(bǔ)MQTT協(xié)議的不足之處:重試的消息ID一定要一致接收方一定判斷當(dāng)前接收的消息ID是否已經(jīng)接受過,但一樣不能夠完全確保世分,消息一定到達(dá)了编振。

QoS level 2

僅僅在PUBLISH類型消息中出現(xiàn)坐桩,要求在可變頭部中要附加消息ID转锈。
  級(jí)別高胜榔,通信壓力稍大些钧舌,但確保了僅僅傳輸接收一次屈梁。
  先看協(xié)議中流程圖络拌,Client -> Server方向乃坤,會(huì)有一個(gè)總體印象:

| Client | Message and direction | Server |
| ------------- |:-------------:|: ----------|
| QoS = 2
DUP = 0
Message ID = x

Action: Store message | PUBLISH
----------> | Actions(a):
Store message
or
Actions(b):
1. Store message
2. Publish message to subscribers |
| Message ID = x| PUBREL
----------> | Actions(a):
1. Publish message to subscribers
2. Delete message
or
Actions(b):
Delete message ID |
| | PUBREC
<---------- | Message ID = x |
| Action: Discard message| PUBCOMP
<---------- | Message ID = x |
針對(duì)服務(wù)器發(fā)布到訂閱者的消息處理流程:

| Server | Message and direction | Subscriber |
| ------------- |:-------------:|: ----------|
| QoS = 2
DUP = 0
Message ID = x

Action: Store message | PUBLISH
----------> | Actions:
Store message |
| | PUBREL
----------> | Message ID = x|
| Message ID = x| PUBREC
<---------- | Actions:
Make message available |
| | PUBCOMP
<---------- | Message ID = x |
  Server端采取的方案a和b旬迹,都包含了何時(shí)消息有效荣恐,何時(shí)處理消息液斜。兩個(gè)方案二選一,Server端自己決定叠穆。但無論死采取哪一種方式少漆,都是在QoS level 2協(xié)議范疇下,不受影響硼被。若一方?jīng)]有接收到對(duì)應(yīng)的確認(rèn)消息示损,會(huì)從最近一次需要確認(rèn)的消息重試,以便整個(gè)(QoS level 2)流程打通嚷硫。

消息順序

消息順序會(huì)受許多因素的影響检访,但對(duì)于服務(wù)器程序,必須保證消息傳遞流程的每個(gè)階段要和開始的順序一致仔掸。例如脆贵,在QoS level 2定義的消息流中,PUBREL流必須和PUBLISH流具有相同的順序發(fā)送:

| Client | Message and direction | Server |
| ------------- |:-------------:|: ----------|
||PUBLISH 1
---------->
PUBLISH 2
---------->
PUBLISH 3
---------->||
||PUBREC 1
<----------
PUBREC 2
<----------||
||PUBREL 1
---------->||
||PUBREC 3
<----------||
||PUBREL 2
---------->||
||PUBCOMP 1
<----------||
||PUBREL 3
---------->||
||PUBCOMP 2
<----------
PUBCOMP 3
<----------||

流動(dòng)消息(in-flight messages)數(shù)量允許有一個(gè)可保證的效果:

  • 在流動(dòng)消息(in-flight)窗口1中嘉汰,每個(gè)傳遞流在下一個(gè)流開始之前完成丹禀。這保證消息以提交的順序傳遞
  • 在流動(dòng)消息(in-flight)大于1的窗口,只能在QoS level內(nèi)被保證消息的順序

消息的持久化

在MQTT協(xié)議中,PUBLISH消息固定頭部RETAIN標(biāo)記双泪,只有為1才要求服務(wù)器需要持久保存此消息持搜,除非新的PUBLISH覆蓋。
  對(duì)于持久的焙矛、最新一條PUBLISH消息葫盼,服務(wù)器不但要發(fā)送給當(dāng)前的訂閱者,并且新的訂閱者(new subscriber村斟,同樣需要訂閱了此消息對(duì)應(yīng)的Topic name)會(huì)馬上得到推送贫导。

Tip:新來乍到的訂閱者,只會(huì)取出最新的一個(gè)RETAIN flag = 1的消息推送蟆盹,不是所有孩灯。

消息流的編碼/解碼

MQTT協(xié)議中,由目前定義的14種類型消息在客戶端和服務(wù)器端之間數(shù)據(jù)進(jìn)行交互逾滥。若以JAVA語(yǔ)言構(gòu)建MQTT服務(wù)器峰档,可選擇Netty作為基礎(chǔ)。
  在Netty中寨昙,數(shù)據(jù)的進(jìn)入和流出讥巡,代表了一次完整的交互。無論是要進(jìn)入的還是要流出的數(shù)據(jù)(單獨(dú)以服務(wù)器為例)舔哪,都可看做字節(jié)流欢顷。若把每種類型消息抽象為一個(gè)具體對(duì)象,那么處理起來就不難了捉蚤。
  客戶端->服務(wù)器抬驴,進(jìn)入的字節(jié)流,逐個(gè)字節(jié)/單位讀取外里,可還原成一個(gè)具體的消息對(duì)象(解碼的過程)怎爵。
  要發(fā)送到客戶端的消息對(duì)象,轉(zhuǎn)換(編碼)成字節(jié)流盅蝗,然后由TCP通道流轉(zhuǎn)到接收者鳖链。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市墩莫,隨后出現(xiàn)的幾起案子芙委,更是在濱河造成了極大的恐慌,老刑警劉巖狂秦,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灌侣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡裂问,警方通過查閱死者的電腦和手機(jī)侧啼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門牛柒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痊乾,你說我怎么就攤上這事皮壁。” “怎么了哪审?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵蛾魄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我湿滓,道長(zhǎng)滴须,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任叽奥,我火速辦了婚禮扔水,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朝氓。我一直安慰自己铭污,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布膀篮。 她就那樣靜靜地躺著,像睡著了一般岂膳。 火紅的嫁衣襯著肌膚如雪誓竿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天谈截,我揣著相機(jī)與錄音筷屡,去河邊找鬼。 笑死簸喂,一個(gè)胖子當(dāng)著我的面吹牛毙死,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喻鳄,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼扼倘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了除呵?” 一聲冷哼從身側(cè)響起再菊,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颜曾,沒想到半個(gè)月后纠拔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡泛豪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年稠诲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侦鹏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡臀叙,死狀恐怖略水,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匹耕,我是刑警寧澤聚请,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站稳其,受9級(jí)特大地震影響驶赏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜既鞠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一煤傍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘱蛋,春花似錦蚯姆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至凶伙,卻和暖如春郭毕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背函荣。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工显押, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人傻挂。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓乘碑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親金拒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兽肤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)殖蚕,斷路器轿衔,智...
    卡卡羅2017閱讀 134,638評(píng)論 18 139
  • 前言 這次要講到客戶端/服務(wù)器的發(fā)布消息行為,與PUBLISH相關(guān)的消息類型睦疫,會(huì)在這里提到害驹。 PUBLISH 客戶...
    技術(shù)學(xué)習(xí)閱讀 5,022評(píng)論 0 2
  • 序 本篇會(huì)把連接(CONNECT)、心跳(PINGREQ/PINGRESP)蛤育、確認(rèn)(CONNACK)宛官、斷開連接(D...
    技術(shù)學(xué)習(xí)閱讀 9,747評(píng)論 0 8
  • MQTT Protocol MQTT協(xié)議特性 一句話總結(jié):MQTT是一個(gè)簡(jiǎn)單葫松,輕量的消息發(fā)布/訂閱協(xié)議。 MQTT...
    傅紫矗克斯記閱讀 7,240評(píng)論 0 9
  • 前言 接到任務(wù)項(xiàng)目需要用MQTT來寫消息推送腋么,經(jīng)過一段時(shí)間在網(wǎng)上查看資料后寫下這篇文章,文章內(nèi)容大都來自互聯(lián)網(wǎng)亥揖,在...
    Hank_Zhong閱讀 16,518評(píng)論 69 51