【轉(zhuǎn)載】移動(dòng)IM開發(fā)之心跳

姓名:何瑞 ????????? 學(xué)號(hào):17021211237

轉(zhuǎn)自:http://www.52im.net/thread-281-1-1.html

本文原作者:項(xiàng)望烽左敌,畢業(yè)于浙江大學(xué)瘾蛋,目前是網(wǎng)易云信 iOS 端研發(fā)負(fù)責(zé)人。

原文連接:http://xiangwangfeng.com/2016/04/12/%E7%A7%BB%E5%8A%A8-IM-%E5%BC%80%E5%8F%91%E4%B9%8B%E5%BF%83%E8%B7%B3/

【嵌牛導(dǎo)讀】:很多人認(rèn)為矫限,TCP協(xié)議自身先天就有KeepAlive機(jī)制哺哼,為何基于它的通訊鏈接,仍然需要在應(yīng)用層實(shí)現(xiàn)額外的心跳钡鸱纾活取董?本文將從移動(dòng)端IM實(shí)踐的角度告訴你,即使使用的是TCP協(xié)議无宿,應(yīng)用層的心跳币鹛活仍舊必不可少。

【嵌牛鼻子】:移動(dòng)端IM開發(fā)孽鸡、進(jìn)程滨逦纾活

【嵌牛提問(wèn)】:為什么需要在應(yīng)用層做心跳,難道 TCP 不是個(gè)可靠連接嗎彬碱?我們不能夠依賴 TCP 做斷線檢測(cè)嗎豆胸?

【嵌牛正文】

一、本文起源

做移動(dòng)端IM多年以來(lái)堡妒,經(jīng)常會(huì)與相關(guān)人員進(jìn)行討論和交流配乱。也經(jīng)常會(huì)碰到些較真的技術(shù)人員詢問(wèn)技術(shù)細(xì)節(jié),如主流的移動(dòng)端IM如何做心跳、如何保證消息必達(dá)搬泥、如何加快文件上傳等桑寨。因?yàn)槠綍r(shí)工作太忙,沒有時(shí)間深入整理和總結(jié)忿檩,往往只能簡(jiǎn)略介紹尉尾,并不能具體展開,于是決定寫成文字燥透,也有了有關(guān)移動(dòng)IM 問(wèn)題處理的系列文章沙咏。

二、什么是心跳卑嗵祝活肢藐?

在使用 TCP 長(zhǎng)連接的 IM 服務(wù)設(shè)計(jì)中,往往都會(huì)涉及到心跳吱韭。心跳一般是指某端(絕大多數(shù)情況下是客戶端)每隔一定時(shí)間向?qū)Χ税l(fā)送自定義指令吆豹,以判斷雙方是否存活,因其按照一定間隔發(fā)送理盆,類似于心跳痘煤,故被稱為心跳指令。

三猿规、TCP協(xié)議不是自帶KeepAlive的嗎衷快?

為什么需要在應(yīng)用層做心跳,難道 TCP 不是個(gè)可靠連接嗎姨俩?我們不能夠依賴 TCP 做斷線檢測(cè)嗎蘸拔?比如使用 TCP 的 KeepAlive 機(jī)制來(lái)實(shí)現(xiàn)。應(yīng)用層心跳是目前的最佳實(shí)踐嗎哼勇?怎么樣的心跳才是最佳實(shí)踐都伪。好吧呕乎,是不是以前從來(lái)沒有仔細(xì)考慮過(guò)這些問(wèn)題积担,僅僅只是個(gè)簡(jiǎn)單的心跳而已啊猬仁!

四帝璧、IM中保持有效長(zhǎng)連接的重要性

對(duì)于客戶端而言,使用 TCP 長(zhǎng)連接來(lái)實(shí)現(xiàn)業(yè)務(wù)的最大驅(qū)動(dòng)力在于:在當(dāng)前連接可用的情況下湿刽,每一次請(qǐng)求都只是簡(jiǎn)單的數(shù)據(jù)發(fā)送和接受的烁,免去了 DNS 解析,連接建立等時(shí)間诈闺,大大加快了請(qǐng)求的速度渴庆,同時(shí)也有利于接受服務(wù)器的實(shí)時(shí)消息。但前提是連接可用。

如果連接無(wú)法很好地保持襟雷,每次請(qǐng)求就會(huì)變成撞大運(yùn):運(yùn)氣好刃滓,通過(guò)長(zhǎng)連接發(fā)送請(qǐng)求并收到反饋。運(yùn)氣差耸弄,當(dāng)前連接已失效咧虎,請(qǐng)求遲遲沒有收到反饋直到超時(shí),又需要一次連接建立的過(guò)程计呈,其效率甚至還不如 HTTP砰诵。而連接保持的前提必然是檢測(cè)連接的可用性,并在連接不可用時(shí)主動(dòng)放棄當(dāng)前連接并建立新的連接捌显。

基于這個(gè)前提茁彭,必須要有一種機(jī)制用于檢測(cè)連接可用性。同時(shí)移動(dòng)網(wǎng)絡(luò)的特殊性也要求客戶端需要在空余時(shí)間發(fā)送一定的信令扶歪,避免連接被回收尉间。詳見微信和運(yùn)營(yíng)商的撕B(另一篇針對(duì)微信的信令風(fēng)暴技術(shù)研究文章請(qǐng)見:《微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析》)。

而對(duì)于服務(wù)器而言击罪,能夠及時(shí)獲悉連接可用性也非常重要:一方面服務(wù)器需要及時(shí)清理無(wú)效連接以減輕負(fù)載哲嘲,另一方面也是業(yè)務(wù)的需求,如游戲副本中服務(wù)器需要及時(shí)處理玩家掉線帶來(lái)的問(wèn)題媳禁。

五眠副、TCP的KeepAlive無(wú)法替代應(yīng)用層心跳保活機(jī)制的原因

上面說(shuō)了保持連接的重要性竣稽,那么現(xiàn)在回到具體實(shí)現(xiàn)上囱怕。為什么我們需要使用應(yīng)用層心跳來(lái)做檢測(cè),而不是直接使用 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è)月裙盾,即使在這期間中間路由崩潰重啟無(wú)數(shù)次实胸。舉個(gè)現(xiàn)實(shí)中經(jīng)常遇到的栗子:當(dāng)我們 ssh 到自己的 VPS 上他嫡,然后不小心踢掉網(wǎng)線,此時(shí)的網(wǎng)絡(luò)變化并不會(huì)被 TCP 檢測(cè)出庐完,當(dāng)我們重新插回網(wǎng)線涮瞻,仍舊可以正常使用 ssh,同時(shí)此時(shí)并沒有發(fā)生任何 TCP 的重連假褪。

有人會(huì)說(shuō) TCP 不是有 KeepAlive 機(jī)制么署咽,通過(guò)這個(gè)機(jī)制來(lái)實(shí)現(xiàn)不就可以了嗎?但是事實(shí)上生音,TCP KeepAlive的機(jī)制其實(shí)并不適用于此宁否。Keep Alive 機(jī)制開啟后,TCP 層將在定時(shí)時(shí)間到后發(fā)送相應(yīng)的 KeepAlive探針以確定連接可用性缀遍。一般時(shí)間為 7200 s慕匠,失敗后重試 10 次,每次超時(shí)時(shí)間 75s域醇。顯然默認(rèn)值無(wú)法滿足我們的需求台谊,而修改過(guò)設(shè)置后就可以滿足了嗎?答案仍舊是否定的譬挚。因?yàn)?TCP KeepAlive是用于檢測(cè)連接的死活锅铅,而心跳機(jī)制則附帶一個(gè)額外的功能:檢測(cè)通訊雙方的存活狀態(tài)。兩者聽起來(lái)似乎是一個(gè)意思减宣,但實(shí)際上卻大相徑庭盐须。考慮一種情況漆腌,某臺(tái)服務(wù)器因?yàn)槟承┰驅(qū)е仑?fù)載超高贼邓,CPU100%,無(wú)法響應(yīng)任何業(yè)務(wù)請(qǐng)求闷尿,但是使用 TCP探針則仍舊能夠確定連接狀態(tài)塑径,這就是典型的連接活著但業(yè)務(wù)提供方已死的狀態(tài),對(duì)客戶端而言填具,這時(shí)的最好選擇就是斷線后重新連接其他服務(wù)器统舀,而不是一直認(rèn)為當(dāng)前服務(wù)器是可用狀態(tài),一直向當(dāng)前服務(wù)器發(fā)送些必然會(huì)失敗的請(qǐng)求灌旧。

從上面我們可以知道绑咱,KeepAlive 并不適用于檢測(cè)雙方存活的場(chǎng)景绰筛,這種場(chǎng)景還得依賴于應(yīng)用層的心跳枢泰。應(yīng)用層心跳有著更大的靈活性,可以控制檢測(cè)時(shí)機(jī)铝噩,間隔和處理流程衡蚂,甚至可以在心跳包上附帶額外信息。從這個(gè)角度而言,應(yīng)用層的心跳的確是最佳實(shí)踐毛甲。

六年叮、心跳保活機(jī)制的實(shí)現(xiàn)方案參考

從上面我們可以得出結(jié)論玻募,目前而言只损,應(yīng)用層心跳的確是檢測(cè)連接有效性,雙方是否存活的最佳實(shí)踐七咧,那么剩下的問(wèn)題就是怎么實(shí)現(xiàn)跃惫。

最簡(jiǎn)單粗暴做法當(dāng)然是定時(shí)心跳,如每隔 30 秒心跳一次艾栋,15秒內(nèi)沒有收到心跳回包則認(rèn)為當(dāng)前連接已失效爆存,斷開連接并進(jìn)行重連。這種做法最直接蝗砾,實(shí)現(xiàn)也簡(jiǎn)單先较。唯一的問(wèn)題是比較耗電和耗流量。以一個(gè)協(xié)議包 5個(gè)字節(jié)計(jì)算悼粮,一天收發(fā) 2880 個(gè)心跳包闲勺,一個(gè)月就是 5 * 2 * 2880 * 30 = 0.8 M 的流量,如果手機(jī)上多裝幾個(gè) IM軟件扣猫,每個(gè)月光心跳就好幾兆流量沒了霉翔,更不用說(shuō)頻繁的心跳帶來(lái)的電量損耗。

既然頻繁心跳會(huì)帶來(lái)耗電和耗流量的弊端苞笨,改進(jìn)的方向自然是減少心跳頻率债朵,但也不能過(guò)于影響連接檢測(cè)的實(shí)時(shí)性∑倌基于這個(gè)需求序芦,一般可以將心跳間隔根據(jù)程序狀態(tài)進(jìn)行調(diào)整,當(dāng)程序在后臺(tái)時(shí)(這里主要考慮安卓)粤咪,盡量拉長(zhǎng)心跳間隔谚中,5分鐘,甚至 10 分鐘都可以寥枝。而當(dāng) App在前臺(tái)時(shí)則按照原來(lái)規(guī)則操作宪塔。連接可靠性的判斷也可以放寬,避免一次心跳超時(shí)就認(rèn)為連接無(wú)效的情況囊拜,使用錯(cuò)誤積累某筐,只在心跳超時(shí) n次后才判定當(dāng)前連接不可用。當(dāng)然還有一些小 trick比如從收到的最后一個(gè)指令包進(jìn)行心跳包周期計(jì)時(shí)而不是固定時(shí)間冠跷,這樣也能夠一定程度減少心跳次數(shù)南誊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末身诺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抄囚,更是在濱河造成了極大的恐慌霉赡,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幔托,死亡現(xiàn)場(chǎng)離奇詭異穴亏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)重挑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門迫肖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人攒驰,你說(shuō)我怎么就攤上這事蟆湖。” “怎么了玻粪?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵隅津,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我劲室,道長(zhǎng)伦仍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任很洋,我火速辦了婚禮充蓝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喉磁。我一直安慰自己谓苟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布协怒。 她就那樣靜靜地躺著涝焙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孕暇。 梳的紋絲不亂的頭發(fā)上仑撞,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音妖滔,去河邊找鬼隧哮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛座舍,可吹牛的內(nèi)容都是我干的沮翔。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼簸州,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鉴竭!你這毒婦竟也來(lái)了歧譬?” 一聲冷哼從身側(cè)響起岸浑,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤搏存,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后矢洲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體璧眠,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年读虏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了责静。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盖桥,死狀恐怖灾螃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揩徊,我是刑警寧澤腰鬼,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站塑荒,受9級(jí)特大地震影響熄赡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜齿税,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一彼硫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凌箕,春花似錦拧篮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至仆葡,卻和暖如春赏参,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沿盅。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工把篓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腰涧。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓韧掩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親窖铡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疗锐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

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

  • 一坊谁、前言 IM發(fā)展至今,已是非常重要的互聯(lián)網(wǎng)應(yīng)用形態(tài)之一滑臊,尤其移動(dòng)互聯(lián)網(wǎng)時(shí)代口芍,它正以無(wú)與論比的優(yōu)勢(shì)降低了溝通成本和...
    Sky109閱讀 4,271評(píng)論 1 60
  • ??本文簡(jiǎn)要的分析了長(zhǎng)連接產(chǎn)生的背景以及所解決的問(wèn)題鬓椭,并對(duì)比了keep-alive與心跳機(jī)制對(duì)長(zhǎng)連接保活的影響关划,最...
    曹豐斌閱讀 9,142評(píng)論 1 20
  • 前言 很多人認(rèn)為,TCP協(xié)議自身先天就有KeepAlive機(jī)制调榄,為何基于它的通訊鏈接踊赠,仍然需要在應(yīng)用層實(shí)現(xiàn)額外的心...
    y角閱讀 1,563評(píng)論 2 10
  • 不能像詩(shī)人一般 幾句詞幾句詩(shī)訴說(shuō)離別想念與不見 可畢竟真的是往事如煙再無(wú)回頭之路 情意在落雨惆悵的深夜寫滿 任你來(lái)...
    哀慕熙榮閱讀 59評(píng)論 0 1
  • 秀菊,是我媽的名字振峻。 有次說(shuō)到這名字臼疫,我說(shuō)很好聽,她不以為然扣孟,“啥好聽不好聽烫堤,那時(shí)候起名都不論,哪像現(xiàn)在凤价,起個(gè)名鸽斟,...
    亦緣君閱讀 332評(píng)論 7 9