1、前言
很多人認(rèn)為,TCP協(xié)議自身先天就有KeepAlive機(jī)制,為何基于它的通訊鏈接,仍然需要在應(yīng)用層實(shí)現(xiàn)額外的心跳保活?本文將從移動(dòng)端IM實(shí)踐的角度告訴你,即使使用的是TCP協(xié)議,應(yīng)用層的心跳保活仍舊必不可少。
有關(guān)TCP協(xié)議的權(quán)威理論介紹,請參見《TCP/IP詳解》這本書。
說明:本文引用了網(wǎng)易云信項(xiàng)望烽的技術(shù)文章,感謝分享。 (本文同步發(fā)布于:http://www.52im.net/thread-33-1-1.html)
2、學(xué)習(xí)交流
- 即時(shí)通訊開發(fā)交流群:
215891622 [推薦]
- 移動(dòng)端IM開發(fā)推薦文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
3、參考資料
《TCP/IP詳解 - 第11章·UDP:用戶數(shù)據(jù)報(bào)協(xié)議》
《TCP/IP詳解 - 第17章·TCP:傳輸控制協(xié)議》
《TCP/IP詳解 - 第18章·TCP連接的建立與終止》
《TCP/IP詳解 - 第21章·TCP的超時(shí)與重傳》
《通俗易懂-深入理解TCP協(xié)議(上):理論基礎(chǔ)》
《通俗易懂-深入理解TCP協(xié)議(下):RTT、滑動(dòng)窗口、擁塞處理》
《理論經(jīng)典:TCP協(xié)議的3次握手與4次揮手過程詳解》
《計(jì)算機(jī)網(wǎng)絡(luò)通訊協(xié)議關(guān)系圖(中文珍藏版)》
《NAT詳解:基本原理、穿越技術(shù)(P2P打洞)、端口老化等》
4、本文源起
做移動(dòng)端IM多年以來,經(jīng)常會(huì)與相關(guān)人員進(jìn)行討論和交流。也經(jīng)常會(huì)碰到些較真的技術(shù)人員詢問技術(shù)細(xì)節(jié),如主流的移動(dòng)端IM如何做心跳、如何保證消息必達(dá)、如何加快文件上傳等。因?yàn)槠綍r(shí)工作太忙,沒有時(shí)間深入整理和總結(jié),往往只能簡略介紹,并不能具體展開,于是決定寫成文字,也有了有關(guān)移動(dòng) IM 問題處理的系列文章。
5、什么是心跳保活?
在使用 TCP 長連接的 IM 服務(wù)設(shè)計(jì)中,往往都會(huì)涉及到心跳。心跳一般是指某端(絕大多數(shù)情況下是客戶端)每隔一定時(shí)間向?qū)Χ税l(fā)送自定義指令,以判斷雙方是否存活,因其按照一定間隔發(fā)送,類似于心跳,故被稱為心跳指令。
有興趣了解IM/推送的心跳保活技術(shù)的文章,請參見:
《Android進(jìn)程保活詳解:一篇文章解決你的所有疑問》
《Android端消息推送總結(jié):實(shí)現(xiàn)原理、心跳保活、遇到的問題等》
《微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺保活實(shí)戰(zhàn)分享(進(jìn)程保活篇)》
《微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺保活實(shí)戰(zhàn)分享(網(wǎng)絡(luò)保活篇)》
《移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制》
《移動(dòng)端IM實(shí)踐:WhatsApp、Line、微信的心跳策略分析》
>> 更多同類文章 ……
6、TCP協(xié)議不是自帶KeepAlive的嗎?
那么問題就隨之而來了:為什么需要在應(yīng)用層做心跳,難道 TCP 不是個(gè)可靠連接嗎?我們不能夠依賴 TCP 做斷線檢測嗎?比如使用 TCP 的 KeepAlive 機(jī)制來實(shí)現(xiàn)。應(yīng)用層心跳是目前的最佳實(shí)踐嗎?怎么樣的心跳才是最佳實(shí)踐。
很多做移動(dòng)端IM的同行,以前確實(shí)沒有仔細(xì)考慮過這些問題,潛意識里想當(dāng)然的認(rèn)為這僅僅只是個(gè)簡單的心跳而已啊。好吧,事實(shí)并非這么簡單,請繼續(xù)往下看。
7、IM中保持有效長連接的重要性
對于客戶端而言,使用 TCP 長連接來實(shí)現(xiàn)業(yè)務(wù)的最大驅(qū)動(dòng)力在于:在當(dāng)前連接可用的情況下,每一次請求都只是簡單的數(shù)據(jù)發(fā)送和接受,免去了 DNS 解析,連接建立等時(shí)間,大大加快了請求的速度,同時(shí)也有利于接受服務(wù)器的實(shí)時(shí)消息。但前提是連接可用。
如果連接無法很好地保持,每次請求就會(huì)變成撞大運(yùn):運(yùn)氣好,通過長連接發(fā)送請求并收到反饋。運(yùn)氣差,當(dāng)前連接已失效,請求遲遲沒有收到反饋直到超時(shí),又需要一次連接建立的過程,其效率甚至還不如 HTTP。而連接保持的前提必然是檢測連接的可用性,并在連接不可用時(shí)主動(dòng)放棄當(dāng)前連接并建立新的連接。
基于這個(gè)前提,必須要有一種機(jī)制用于檢測連接可用性。同時(shí)移動(dòng)網(wǎng)絡(luò)的特殊性也要求客戶端需要在空余時(shí)間發(fā)送一定的信令,避免連接被回收。詳見微信和運(yùn)營商的撕B(另一篇針對微信的信令風(fēng)暴技術(shù)研究文章請見:《微信對網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析》)。
而對于服務(wù)器而言,能夠及時(shí)獲悉連接可用性也非常重要:一方面服務(wù)器需要及時(shí)清理無效連接以減輕負(fù)載,另一方面也是業(yè)務(wù)的需求,如游戲副本中服務(wù)器需要及時(shí)處理玩家掉線帶來的問題。
8、TCP的KeepAlive無法替代應(yīng)用層心跳保活機(jī)制的原因
上面說了保持連接的重要性,那么現(xiàn)在回到具體實(shí)現(xiàn)上。為什么我們需要使用應(yīng)用層心跳來做檢測,而不是直接使用 TCP 的特性呢?
我們知道 TCP 是一個(gè)基于連接的協(xié)議,其連接狀態(tài)是由一個(gè)狀態(tài)機(jī)進(jìn)行維護(hù),連接完畢后,雙方都會(huì)處于 established 狀態(tài),這之后的狀態(tài)并不會(huì)主動(dòng)進(jìn)行變化。這意味著如果上層不進(jìn)行任何調(diào)用,一直使 TCP 連接空閑,那么這個(gè)連接雖然沒有任何數(shù)據(jù),但仍是保持連接狀態(tài),一天、一星期、甚至一個(gè)月,即使在這期間中間路由崩潰重啟無數(shù)次。舉個(gè)現(xiàn)實(shí)中經(jīng)常遇到的栗子:當(dāng)我們 ssh 到自己的 VPS 上,然后不小心踢掉網(wǎng)線,此時(shí)的網(wǎng)絡(luò)變化并不會(huì)被 TCP 檢測出,當(dāng)我們重新插回網(wǎng)線,仍舊可以正常使用 ssh,同時(shí)此時(shí)并沒有發(fā)生任何 TCP 的重連。
有人會(huì)說 TCP 不是有 KeepAlive 機(jī)制么,通過這個(gè)機(jī)制來實(shí)現(xiàn)不就可以了嗎?但是事實(shí)上,TCP KeepAlive 的機(jī)制其實(shí)并不適用于此。Keep Alive 機(jī)制開啟后,TCP 層將在定時(shí)時(shí)間到后發(fā)送相應(yīng)的 KeepAlive 探針以確定連接可用性。一般時(shí)間為 7200 s(詳情請參見《TCP/IP詳解》中第23章),失敗后重試 10 次,每次超時(shí)時(shí)間 75 s。顯然默認(rèn)值無法滿足我們的需求,而修改過設(shè)置后就可以滿足了嗎?答案仍舊是否定的。
因?yàn)?TCP KeepAlive 是用于檢測連接的死活,而心跳機(jī)制則附帶一個(gè)額外的功能:檢測通訊雙方的存活狀態(tài)。兩者聽起來似乎是一個(gè)意思,但實(shí)際上卻大相徑庭。
考慮一種情況,某臺服務(wù)器因?yàn)槟承┰驅(qū)е仑?fù)載超高,CPU 100%,無法響應(yīng)任何業(yè)務(wù)請求,但是使用 TCP 探針則仍舊能夠確定連接狀態(tài),這就是典型的連接活著但業(yè)務(wù)提供方已死的狀態(tài),對客戶端而言,這時(shí)的最好選擇就是斷線后重新連接其他服務(wù)器,而不是一直認(rèn)為當(dāng)前服務(wù)器是可用狀態(tài),一直向當(dāng)前服務(wù)器發(fā)送些必然會(huì)失敗的請求。
從上面我們可以知道,KeepAlive 并不適用于檢測雙方存活的場景,這種場景還得依賴于應(yīng)用層的心跳。應(yīng)用層心跳有著更大的靈活性,可以控制檢測時(shí)機(jī),間隔和處理流程,甚至可以在心跳包上附帶額外信息。從這個(gè)角度而言,應(yīng)用層的心跳的確是最佳實(shí)踐。
9、心跳保活機(jī)制的實(shí)現(xiàn)方案參考
從上面我們可以得出結(jié)論,目前而言,應(yīng)用層心跳的確是檢測連接有效性,雙方是否存活的最佳實(shí)踐,那么剩下的問題就是怎么實(shí)現(xiàn)。
最簡單粗暴做法當(dāng)然是定時(shí)心跳,如每隔 30 秒心跳一次,15 秒內(nèi)沒有收到心跳回包則認(rèn)為當(dāng)前連接已失效,斷開連接并進(jìn)行重連。這種做法最直接,實(shí)現(xiàn)也簡單。唯一的問題是比較耗電和耗流量。以一個(gè)協(xié)議包 5 個(gè)字節(jié)計(jì)算,一天收發(fā) 2880 個(gè)心跳包,一個(gè)月就是 5 * 2 * 2880 * 30 = 0.8 M 的流量,如果手機(jī)上多裝幾個(gè) IM 軟件,每個(gè)月光心跳就好幾兆流量沒了,更不用說頻繁的心跳帶來的電量損耗。
既然頻繁心跳會(huì)帶來耗電和耗流量的弊端,改進(jìn)的方向自然是減少心跳頻率,但也不能過于影響連接檢測的實(shí)時(shí)性。基于這個(gè)需求,一般可以將心跳間隔根據(jù)程序狀態(tài)進(jìn)行調(diào)整,當(dāng)程序在后臺時(shí)(這里主要考慮安卓),盡量拉長心跳間隔,5 分鐘、甚至 10 分鐘都可以。
而當(dāng) App 在前臺時(shí)則按照原來規(guī)則操作。連接可靠性的判斷也可以放寬,避免一次心跳超時(shí)就認(rèn)為連接無效的情況,使用錯(cuò)誤積累,只在心跳超時(shí) n 次后才判定當(dāng)前連接不可用。當(dāng)然還有一些小 trick 比如從收到的最后一個(gè)指令包進(jìn)行心跳包周期計(jì)時(shí)而不是固定時(shí)間,這樣也能夠一定程度減少心跳次數(shù)。
(本文同步發(fā)布于:http://www.52im.net/thread-33-1-1.html)
附錄:更多IM技術(shù)文章
[1] 更多網(wǎng)絡(luò)編程基礎(chǔ)資料:
《理論聯(lián)系實(shí)際:Wireshark抓包分析TCP 3次握手、4次揮手過程》
《UDP中一個(gè)包的大小最大能多大?》
《Java新一代網(wǎng)絡(luò)編程模型AIO原理及Linux系統(tǒng)AIO介紹》
《NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實(shí)戰(zhàn)》
《NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實(shí)戰(zhàn)》
>> 更多同類文章 ……
[2] 有關(guān)IM/推送的通信格式、協(xié)議的選擇:
《為什么QQ用的是UDP協(xié)議而不是TCP協(xié)議?》
《移動(dòng)端即時(shí)通訊協(xié)議選擇:UDP還是TCP?》
《如何選擇即時(shí)通訊應(yīng)用的數(shù)據(jù)傳輸格式》
《強(qiáng)列建議將Protobuf作為你的即時(shí)通訊應(yīng)用數(shù)據(jù)傳輸格式》
《移動(dòng)端IM開發(fā)需要面對的技術(shù)問題(含通信協(xié)議選擇)》
《簡述移動(dòng)端IM開發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》
《理論聯(lián)系實(shí)際:一套典型的IM通信協(xié)議設(shè)計(jì)詳解》
《58到家實(shí)時(shí)消息系統(tǒng)的協(xié)議設(shè)計(jì)等技術(shù)實(shí)踐分享》
>> 更多同類文章 ……
[4] 有關(guān)WEB端即時(shí)通訊開發(fā):
《新手入門貼:史上最全Web端即時(shí)通訊技術(shù)原理詳解》
《Web端即時(shí)通訊技術(shù)盤點(diǎn):短輪詢、Comet、Websocket、SSE》
《SSE技術(shù)詳解:一種全新的HTML5服務(wù)器推送事件技術(shù)》
《Comet技術(shù)詳解:基于HTTP長連接的Web端實(shí)時(shí)通信技術(shù)》
《WebSocket詳解(一):初步認(rèn)識WebSocket技術(shù)》
《socket.io實(shí)現(xiàn)消息推送的一點(diǎn)實(shí)踐及思路》
>> 更多同類文章 ……
[5] 有關(guān)IM架構(gòu)設(shè)計(jì):
《淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)》
《簡述移動(dòng)端IM開發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》
《一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案》
《從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程》
《蘑菇街即時(shí)通訊/IM服務(wù)器開發(fā)之架構(gòu)選擇》
《騰訊QQ1.4億在線用戶的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT》
《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(演講全文)》
《如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡》》
《快速裂變:見證微信強(qiáng)大后臺架構(gòu)從0到1的演進(jìn)歷程(一)》
《17年的實(shí)踐:騰訊海量產(chǎn)品的技術(shù)方法論》
>> 更多同類文章 ……
[6] 有關(guān)IM安全的文章:
《即時(shí)通訊安全篇(一):正確地理解和使用Android端加密算法》
《即時(shí)通訊安全篇(二):探討組合加密算法在IM中的應(yīng)用》
《即時(shí)通訊安全篇(三):常用加解密算法與通訊安全講解》
《即時(shí)通訊安全篇(四):實(shí)例分析Android中密鑰硬編碼的風(fēng)險(xiǎn)》
《傳輸層安全協(xié)議SSL/TLS的Java平臺實(shí)現(xiàn)簡介和Demo演示》
《理論聯(lián)系實(shí)際:一套典型的IM通信協(xié)議設(shè)計(jì)詳解(含安全層設(shè)計(jì))》
《微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解》
《來自阿里OpenIM:打造安全可靠即時(shí)通訊服務(wù)的技術(shù)實(shí)踐分享》
>> 更多同類文章 ……
[7] 有關(guān)實(shí)時(shí)音視頻開發(fā):
《即時(shí)通訊音視頻開發(fā)(一):視頻編解碼之理論概述》
《即時(shí)通訊音視頻開發(fā)(二):視頻編解碼之?dāng)?shù)字視頻介紹》
《即時(shí)通訊音視頻開發(fā)(三):視頻編解碼之編碼基礎(chǔ)》
《即時(shí)通訊音視頻開發(fā)(四):視頻編解碼之預(yù)測技術(shù)介紹》
《即時(shí)通訊音視頻開發(fā)(五):認(rèn)識主流視頻編碼技術(shù)H.264》
《即時(shí)通訊音視頻開發(fā)(六):如何開始音頻編解碼技術(shù)的學(xué)習(xí)》
《即時(shí)通訊音視頻開發(fā)(七):音頻基礎(chǔ)及編碼原理入門》
《即時(shí)通訊音視頻開發(fā)(八):常見的實(shí)時(shí)語音通訊編碼標(biāo)準(zhǔn)》
《即時(shí)通訊音視頻開發(fā)(九):實(shí)時(shí)語音通訊的回音及回音消除概述》
《即時(shí)通訊音視頻開發(fā)(十):實(shí)時(shí)語音通訊的回音消除技術(shù)詳解》
《即時(shí)通訊音視頻開發(fā)(十一):實(shí)時(shí)語音通訊丟包補(bǔ)償技術(shù)詳解》
《即時(shí)通訊音視頻開發(fā)(十二):多人實(shí)時(shí)音視頻聊天架構(gòu)探討》
《即時(shí)通訊音視頻開發(fā)(十三):實(shí)時(shí)視頻編碼H.264的特點(diǎn)與優(yōu)勢》
《即時(shí)通訊音視頻開發(fā)(十四):實(shí)時(shí)音視頻數(shù)據(jù)傳輸協(xié)議介紹》
《即時(shí)通訊音視頻開發(fā)(十五):聊聊P2P與實(shí)時(shí)音視頻的應(yīng)用情況》
《即時(shí)通訊音視頻開發(fā)(十六):移動(dòng)端實(shí)時(shí)音視頻開發(fā)的幾個(gè)建議》
《即時(shí)通訊音視頻開發(fā)(十七):視頻編碼H.264、V8的前世今生》
《簡述開源實(shí)時(shí)音視頻技術(shù)WebRTC的優(yōu)缺點(diǎn)》
《良心分享:WebRTC 零基礎(chǔ)開發(fā)者教程(中文)》
>> 更多同類文章 ……
[8] IM開發(fā)綜合文章:
《移動(dòng)端IM開發(fā)需要面對的技術(shù)問題》
《開發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?》
《請問有人知道語音留言聊天的主流實(shí)現(xiàn)方式嗎?》
《IM系統(tǒng)中如何保證消息的可靠投遞(即QoS機(jī)制)》
《談?wù)勔苿?dòng)端 IM 開發(fā)中登錄請求的優(yōu)化》
《完全自已開發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?》
《微信對網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)》
《即時(shí)通訊系統(tǒng)的原理、技術(shù)和應(yīng)用(技術(shù)論文)》
《開源IM工程“蘑菇街TeamTalk”的現(xiàn)狀:一場有始無終的開源秀》
>> 更多同類文章 ……
[9] 開源移動(dòng)端IM技術(shù)框架資料:
《開源移動(dòng)端IM技術(shù)框架MobileIMSDK:快速入門》
《開源移動(dòng)端IM技術(shù)框架MobileIMSDK:常見問題解答》
《開源移動(dòng)端IM技術(shù)框架MobileIMSDK:壓力測試報(bào)告》
>> 更多同類文章 ……
[10] 有關(guān)推送技術(shù)的文章:
《iOS的推送服務(wù)APNs詳解:設(shè)計(jì)思路、技術(shù)原理及缺陷等》
《Android端消息推送總結(jié):實(shí)現(xiàn)原理、心跳保活、遇到的問題等》
《掃盲貼:認(rèn)識MQTT通信協(xié)議》
《一個(gè)基于MQTT通信協(xié)議的完整Android推送Demo》
《求教android消息推送:GCM、XMPP、MQTT三種方案的優(yōu)劣》
《移動(dòng)端實(shí)時(shí)消息推送技術(shù)淺析》
《掃盲貼:淺談iOS和Android后臺實(shí)時(shí)消息推送的原理和區(qū)別》
《絕對干貨:基于Netty實(shí)現(xiàn)海量接入的推送服務(wù)技術(shù)要點(diǎn)》
《移動(dòng)端IM實(shí)踐:谷歌消息推送服務(wù)(GCM)研究(來自微信)》
《為何微信、QQ這樣的IM工具不使用GCM服務(wù)推送消息?》
>> 更多同類文章 ……
[11] 更多即時(shí)通訊技術(shù)好文分類:
http://www.52im.net/forum.php?mod=collection&op=all