<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學習的點點滴滴。

    MQTT 3.1協(xié)議非嚴肅反思錄

    前言

    MQTT 3.1協(xié)議在弱網(wǎng)絡(luò)環(huán)境下(比如2G/3G等)表現(xiàn)不夠好,因此才有了反思。

    弱網(wǎng)環(huán)境下表現(xiàn)

    手機等終端在弱網(wǎng)絡(luò)環(huán)境下丟包情況會非常明顯,連接MQTT Server成功率很低。相比單純的請求-相應(yīng)模型的HTTP,其成功率會比MQTT訂閱成功高很多。

    手機終端在每次TCP斷開或斷網(wǎng)后,會即刻發(fā)起TCP重連,連接成功,會重復以前步驟依次發(fā)送連接命令(CONNECT),訂閱命令(SUBSCRIBLE),表明上看,這些過程沒有任何問題,但問題就在于從終端成功建立到服務(wù)器的連接,到發(fā)送訂閱命令,在弱網(wǎng)情況下,這個過程將會變得很昂貴:

    從TCP建立開始的三次握手到完整的訂閱命令發(fā)送完畢,考慮到TCP堆棧的每次接收數(shù)據(jù)方響應(yīng)ACK,這中間終端和服務(wù)器端至少產(chǎn)生了10次數(shù)據(jù)交互。
    

    在網(wǎng)絡(luò)變化頻繁或者不太穩(wěn)定的2G/3G網(wǎng)絡(luò)環(huán)境下,這種過程顯得有些冗長和不適應(yīng),同時會加重已經(jīng)不堪的弱網(wǎng)絡(luò)負載的負擔。

    弱網(wǎng)下,在任何一個階段的執(zhí)行過程中,都有可能產(chǎn)生突發(fā)性的網(wǎng)絡(luò)中斷的問題:

    1. 無法成功建立TCP鏈接,或死在三次握手期間,或數(shù)據(jù)包丟失在握手之后,或客戶端連接超時過小

    2. 建立連接后,發(fā)送CONNECT命令后,或沒接收到TCP ACK確認包,或客戶端等待延時太小,導致訂閱命令交互失敗

    3. 發(fā)送SUBSCRIBLE命令后,但服務(wù)器端沒收到,或因為丟包,或網(wǎng)絡(luò)已斷開,導致發(fā)送SUBSCRIBLE命令失敗

    4. 成功發(fā)送SUBSCRIBLE命令后,或移動網(wǎng)絡(luò)斷開了(有些運營商針對認為HTTP的請求有超時判斷),或等待超時,導致訂閱失敗

    TCP是無感知的虛擬連接,中間斷開兩端不會立刻得到通知,否則就用不著心跳保活機制了。

    舉一個例子,線上的服務(wù)器根據(jù)日志分析,只接收到連接命令(CONNECT)但沒有后續(xù)的訂閱命令(SUBSCRIBLE)的情況,每天有上百萬級別的數(shù)量。

    總之,針對低速率弱網(wǎng)絡(luò)環(huán)境,MQTT表現(xiàn)不怎么好。

    改進點

    業(yè)務(wù)改進點:

    1. 客戶端的連接超時、等待超時設(shè)大一點,兩秒太短,可設(shè)置長一些,比如10秒
    2. 服務(wù)器端支持在接收到用戶發(fā)送CONNECT命令后,瞬間發(fā)送一些live data/hot data(早已緩存的數(shù)據(jù)),類似于HTTP請求-相應(yīng)模型,目的嘛,一些熱數(shù)據(jù)發(fā)送給終端要趁早,越快越好(所謂出名要趁早嘛);這個需要客戶端、服務(wù)器端同時支持

    協(xié)議改進點:

    1. CONNECT命令可變頭部包含"MQisdp"太多余了,學院派風格嘛
    2. 允許在連接命令中負載(payload)中攜帶訂閱Topic字符串
    3. 允許在連接命令中表示上次連接訂閱的Topic發(fā)生變化否,攜帶訂閱業(yè)務(wù),雖冗余,但實用。 eg:訂閱的Topic沒有發(fā)生變化,TOPICCHANGE:0;退訂,UNSUBSCRIBE:TOPICONE;SUBSCRIBE:TOPIC_TWO
    4. PUBLISH、PUBACK等支持的 Message Identifier 才16位,太短,實際業(yè)務(wù)無法做到全局唯一。引入mid和業(yè)務(wù)id的映射對應(yīng)關(guān)系?那是狀態(tài),需要維護,代價還是蠻高的。業(yè)界流行看法,無狀態(tài)化的架構(gòu)才是便于橫向、豎向、縱向、四方向的擴展,呵呵。最好方式就是修改使之支持字符串形式,否則維護代價高!
    5. 心跳命令PINGREQ/PINGREQ可以做到一個字節(jié)傳輸,節(jié)省一個字節(jié),有些強迫癥的感覺嘛
    6. 低速率網(wǎng)絡(luò)需要做一些兼容和調(diào)整

    有些建議看似冗余,批量或打包處理總比單個處理更高效一些、更節(jié)省資源,弱網(wǎng)絡(luò)環(huán)境要求交互要盡可能的少,數(shù)據(jù)嘛要的是瞬間抵達,越快越好。

    嚴格的分層和業(yè)務(wù)解耦,會導致性能問題。好比當前Linux內(nèi)核的TCP/IP網(wǎng)絡(luò)堆棧分層很清晰,每一層都各司其職,但和直接略過內(nèi)核態(tài)直接運行在用戶態(tài)(User Space)的Packet I/O相比,處理性能不是在一個檔次上,比如Netmap 、DPDK等。

    MQTT-SN

    針對沒有TCP/IP等網(wǎng)絡(luò)堆棧支持的終端環(huán)境,MQTT愛莫能助了。

    在一些類似于傳感器電子元件中,資源十分受限,計算能力不足,嵌入TCP/IP網(wǎng)絡(luò)堆棧不現(xiàn)實,比較好的方式基于IEEE 802.15.4用于低速無線個人域網(wǎng)(LR-WPAN)的物理層和媒體接入控制層規(guī)范之上發(fā)送UDP數(shù)據(jù)包,每一個數(shù)據(jù)包最大128個字節(jié)。

    MQTT-SN(MQTT For Sensor Networks)協(xié)議就是為了非常受限類似傳感器而設(shè)的,協(xié)議流程架構(gòu)比較有趣:

    Image

    更多協(xié)議細節(jié),有待進一步閱讀。

    TCP不是最適合的移動網(wǎng)絡(luò)傳輸協(xié)議

    先來算一下網(wǎng)絡(luò)傳輸?shù)淖止?jié)數(shù)。

    以太網(wǎng)幀頭至少18個字節(jié),IP頭固定20個字節(jié),TCP頭20個字節(jié)(UDP頭部8個字節(jié)),再加上電信寬帶計費的PPPoE的8個字節(jié):

    • TCP數(shù)據(jù)包頭部信息至少占有66個字節(jié)
    • UDP數(shù)據(jù)報頭部信息至少占有54個字節(jié)

    UDP可以比TCP節(jié)省12個字節(jié)。

    MQTT-SN協(xié)議選擇使用UDP,可以看出其在節(jié)省資源方面的努力。

    再看看弱網(wǎng)環(huán)境。

    • 在網(wǎng)絡(luò)可達情況下,UDP可以在TCP建立第一次握手期間就已經(jīng)把數(shù)據(jù)送達目的地
    • 完成三次握手期間,UDP客戶端和UDP服務(wù)器在數(shù)據(jù)層面可以完成一次完整的交互(PING-PONG)

    在網(wǎng)絡(luò)不好的情況下,UDP的時效性會好于TCP,TCP長連接中間交換過多、使之建立完整交互的過程成功率就很低。此種情況UDP的低延遲和實時性呈現(xiàn)的結(jié)果會表現(xiàn)的很突出。

    TCP或HTTP理論上是可靠連接,但是在網(wǎng)絡(luò)不好的時候,也不是那么可靠。客戶端一般提交HTTP請求之后,沒有確認是否提交成功,在弱網(wǎng)環(huán)境下會產(chǎn)生丟包,服務(wù)器端嘛收不到。另TCP網(wǎng)絡(luò)堆棧會存在數(shù)據(jù)包重發(fā)機制 + 應(yīng)用層重發(fā)請求,可能會導致內(nèi)核處理多次數(shù)據(jù)包的重發(fā)(還有擁塞窗口會收縮,發(fā)包速度減慢),可能會加重弱網(wǎng)絡(luò)的負載。

    和TCP相比,UDP的無連接,代表了它快速,資源消耗小,突出表現(xiàn)就是延遲較小。至于數(shù)據(jù)包丟失沒有重傳,上層的業(yè)務(wù)層面應(yīng)用協(xié)議/機制可以確保丟失的數(shù)據(jù)包重發(fā)或補發(fā)等,并且會更透明,安全的控性權(quán)。而TCP的包重發(fā),上層應(yīng)用沒有控制權(quán)限。

    連接協(xié)議方面:

    • TCP面向連接會產(chǎn)生狀態(tài)管理和維護,成本不小,比如經(jīng)常看到的客戶端reset異常等。一次完整的請求周期必須固定在一臺服務(wù)器上
    • UDP無連接的特性。每次請求的數(shù)據(jù)包可以隨機分配到不同的機器上進行處理,可以做到完全無狀態(tài)化橫向擴展

    總之,要實時性特診,或者快速抵達終端的特性,不妨考慮一下UDP。不過呢,很多時候UDP和TCP大家會混合著使用,會互相彌補其不足。

    小結(jié)

    若MQTT協(xié)議不能夠滿足業(yè)務(wù)需求,或許可考慮選擇定制,或簡化流程,或使用UDP重新實現(xiàn),或者使用TCP/HTTP作為補充等,不一而足。

    想想,還真有點小激動呢! ------ 《萬萬沒想到》王大錘

    posted on 2014-12-12 10:19 nieyong 閱讀(31301) 評論(17)  編輯  收藏 所屬分類: MQTT

    評論

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2014-12-16 17:20 tangsir

    你好,謝謝你的文章。
    我們有個手機APP,目前的方案是實時數(shù)據(jù)直接socket連接(不好的地方是客戶端服務(wù)端都要寫代碼),想全面轉(zhuǎn)向mqtt(這樣服務(wù)端就專注于從mqtt對立里面獲取數(shù)據(jù),進行業(yè)務(wù)處理,并發(fā)送消息即可),邏輯上應(yīng)該更清楚,代碼開發(fā)也方便。但是聽你這個介紹有點猶豫了,要不要改呢?請聽你的指教!  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2014-12-17 10:25 nieyong

    @tangsir
    目前除了MQTT,暫時找不到比它更好的業(yè)界標準了。建議選擇MQTT 3.1.1協(xié)議:
    支持客戶端在發(fā)送完畢CONNECT之后,無須等待服務(wù)器響應(yīng)直接發(fā)送其余命令
    支持服務(wù)器和客戶端兩端暫時會話保存,上次連接之后,再次CONNECT,會話標志位true,可無須發(fā)送SUBSCRIBLE命令
    具體請參考:
    MQTT 3.1.1,值得升級的6個新特性  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2014-12-17 23:21 tangsir

    謝大神!@nieyong
      回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2014-12-18 22:06 nieyong

    @tangsir
    措辭有問題,可不是什么大神,呵呵。
    只是總結(jié)而已。  回復  更多評論   

    # Bad Piggies Game 2014-12-19 15:55 Bad Piggies Game

    措辭有問題,可不是什么大神,呵呵。  回復  更多評論   

    # Jogos Frin 2014-12-22 11:55 friv4school2015@hotmail.com

    措辭有問題,可不是什么大神,呵呵。  回復  更多評論   

    # Jogos Frin 2014-12-22 11:55 friv4school2015@hotmail.com

    措辭有問題,可不是什么大神,呵呵。   回復  更多評論   

    # Friv School 2015 2014-12-25 11:07 yepimatasa

    措辭有問題,可不是什么大神,呵呵  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-07 21:33 kdm

    你好我們有手機設(shè)備也有硬件設(shè)備,不同的設(shè)備需要根據(jù)不同的情況推送各自的數(shù)據(jù),如果我們有10萬個終端,我們需要建立10萬個topic嗎?有沒有其它地方法謝謝?  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-08 09:49 nieyong

    @kdm
    其實,靈活一點是不需要建立10W個topic的,根據(jù)clientId就可以  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-14 21:53 kdm

    @nieyong
    請教一下根據(jù)clientId如何做,請大神指導  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-15 10:04 nieyong

    @kdm
    clientId等同于topic就行  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-15 17:45 kdm

    @nieyong
    那還是每個設(shè)備一個topic對吧。topic的主題為clientId.  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-05-18 16:41 nieyong

    @kdm
    是的,比如根據(jù)協(xié)議,只需要注冊一次,服務(wù)器端可持久化topic和clientId的對應(yīng)關(guān)系,后面不需要再次注冊等。或者再簡單一些,就直接根據(jù)clientId作為topic就行。

    怎么說呢,越是海量用戶/終端的系統(tǒng),協(xié)議交互層面需要越簡單,架構(gòu)層面也是如此。  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-06-12 13:56 Justin Gao

    看了這篇文章,實話說有點不以為然

    本文說了半天,就是一個問題,當subscribe命令在交互時候出現(xiàn)問題怎么辦?

    回到協(xié)議本身,事實上是很簡單的一個答案,只有收到正確的suback命令才能認為subscribe成功,否則客戶端有義務(wù)不斷地重復發(fā)送subscribe。

    而判斷正確返回否則管理著重發(fā)的機制本來就是message queue的精髓所在,在客戶端維護一個最基礎(chǔ)記錄subscribe的queue,原始意義上并不是特別難。

    至于本文所提的用UDP協(xié)議,或者和改造協(xié)議部分,重傳部分數(shù)據(jù)的方法,只會使協(xié)議復雜度變高很多,出錯可能性增加;在高并發(fā)的環(huán)境中,并不可取。而相對來說,客戶端做更改難度小很多。  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2015-09-13 09:32 mqtt

    subscribe讓服務(wù)器自動訂閱,把客戶端subscribe功能禁止掉  回復  更多評論   

    # re: MQTT 3.1協(xié)議非嚴肅反思錄 2016-05-23 07:34 Jammers

    This is very nice. Thank you.  回復  更多評論   

    公告

    所有文章皆為原創(chuàng),若轉(zhuǎn)載請標明出處,謝謝~

    新浪微博,歡迎關(guān)注:

    導航

    <2015年5月>
    262728293012
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    統(tǒng)計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲人成人网站在线观看| 337p日本欧洲亚洲大胆精品555588| 国产精品玖玖美女张开腿让男人桶爽免费看 | 亚洲色图在线观看| 成年女人免费视频播放77777| 免费无码又爽又黄又刺激网站| 久久精品国产亚洲av四虎| 成人毛片免费视频| 91视频精品全国免费观看| 久久精品国产亚洲AV忘忧草18 | 亚洲狠狠成人综合网| 亚洲人成人网站在线观看| 免费观看无遮挡www的视频| 最新亚洲人成网站在线观看| 亚洲AV乱码久久精品蜜桃 | 亚洲欧美日韩中文无线码| 亚洲人成人网站色www| 成人免费无码大片A毛片抽搐| 女同免费毛片在线播放| 亚洲国产精品成人综合色在线| 国产亚洲精品国产| 国产jizzjizz视频免费看| 国产精彩免费视频| 99视频在线免费观看| 亚洲AV无码一区二区乱子仑 | 亚洲午夜一区二区电影院| 中文字幕人成人乱码亚洲电影| 毛色毛片免费观看| 最近2018中文字幕免费视频| 又黄又大的激情视频在线观看免费视频社区在线 | 亚洲精品国产综合久久久久紧| 亚洲精品高清久久| 亚洲综合无码精品一区二区三区| 四色在线精品免费观看| 四虎在线视频免费观看视频| 精品国产免费一区二区三区香蕉| 一级全免费视频播放| 国产亚洲精品美女久久久久久下载| 亚洲乱码一区二区三区国产精品| 亚洲人成网站影音先锋播放| 亚洲精品成人片在线播放|