移動IM開發指南2 心跳指令詳解

2021-09-11 11:51:44 字數 2014 閱讀 2322

網易雲信多年ios

im sdk開發的經驗,深度分析實際開發中的各種常見問題。

移動im開發指南1:如何進行技術選型

移動im開發指南3:如何優化登入模組

在使用 tcp 長連線的 im 服務設計中,往往都會涉及到心跳。心跳一般是指某端(絕大多數情況下是客戶端)每隔一定時間向對端傳送自定義指令,以判斷雙方是否存活,因其按照一定間隔傳送,類似於心跳,故被稱為心跳指令。

那麼為什麼需要在應用層做心跳,難道 tcp 不是個可靠連線嗎?我們不能夠依賴 tcp 做斷線檢測嗎?比如使用 tcp 的 keepalive 機制來實現。應用層心跳是目前的最佳實踐嗎?怎麼樣的心跳才是最佳實踐?

是不是以前從來沒有仔細考慮過這些問題,僅僅只是個簡單的心跳而已啊!

對於客戶端而言,使用 tcp 長連線來實現業務的最大驅動力在於:在當前連線可用的情況下,每一次請求都只是簡單的資料傳送和接受,免去了 dns 解析,連線建立等時間,大大加快了請求的速度,同時也有利於接受伺服器的實時訊息。

但前提是連線可用。如果連線無法很好地保持,每次請求就會變成撞大運:運氣好,通過長連線傳送請求並收到反饋。運氣差,當前連線已失效,請求遲遲沒有收到反饋直到超時,又需要一次連線建立的過程,其效率甚至還不如 http。而連線保持的前提必然是檢測連線的可用性,並在連線不可用時主動放棄當前連線並建立新的連線。

而對於伺服器而言,能夠及時獲悉連線可用性也非常重要:一方面伺服器需要及時清理無效連線以減輕負載,另一方面也是業務的需求,如遊戲副本中伺服器需要及時處理玩家掉線帶來的問題。

上面說了保持連線的重要性,那麼現在回到具體實現上。為什麼我們需要使用應用層心跳來做檢測,而不是直接使用 tcp 的特性呢?

我們知道 tcp 是乙個基於連線的協議,其連線狀態是由乙個狀態機進行維護,連線完畢後,雙方都會處於 established 狀態,這之後的狀態並不會主動進行變化。這意味著如果上層不進行任何呼叫,一直使 tcp 連線空閒,那麼這個連線雖然沒有任何資料,但仍是保持連線狀態,一天,一星期,甚至乙個月,即使在這期間中間路由崩潰重啟無數次。舉個現實中經常遇到的栗子:當我們 ssh 到自己的 vps 上,然後不小心踢掉網線,此時的網路變化並不會被 tcp 檢測出,當我們重新插回網線,仍舊可以正常使用 ssh,同時此時並沒有發生任何 tcp 的重連。

有人會說 tcp 不是有 keepalive 機制麼,通過這個機制來實現不就可以了嗎?但是事實上,tcp keepalive 的機制其實並不適用於此。keep alive 機制開啟後,tcp 層將在定時時間到後傳送相應的 keepalive 探針以確定連線可用性。一般時間為 7200 s,失敗後重試 10 次,每次超時時間 75 s。顯然預設值無法滿足我們的需求,而修改過設定後就可以滿足了嗎?答案仍舊是否定的。因為 tcp keepalive 是用於檢測連線的死活,而心跳機制則附帶乙個額外的功能:檢測通訊雙方的存活狀態。兩者聽起來似乎是乙個意思,但實際上卻大相徑庭。考慮一種情況,某台伺服器因為某些原因導致負載超高,cpu 100%,無法響應任何業務請求,但是使用 tcp 探針則仍舊能夠確定連線狀態,這就是典型的連線活著但業務提供方已死的狀態,對客戶端而言,這時的最好選擇就是斷線後重新連線其他伺服器,而不是一直認為當前伺服器是可用狀態,一直向當前伺服器傳送些必然會失敗的請求。

從上面我們可以知道,keepalive 並不適用於檢測雙方存活的場景,這種場景還得依賴於應用層的心跳。應用層心跳有著更大的靈活性,可以控制檢測時機,間隔和處理流程,甚至可以在心跳包上附帶額外資訊。從這個角度而言,應用層的心跳的確是最佳實踐。

從上面我們可以得出結論,目前而言,應用層心跳的確是檢測連線有效性,雙方是否存活的最佳實踐,那麼剩下的問題就是怎麼實現。

最簡單粗暴做法當然是定時心跳,如每隔 30 秒心跳一次,15 秒內沒有收到心跳回包則認為當前連線已失效,斷開連線並進行重連。這種做法最直接,實現也簡單。唯一的問題是比較耗電和耗流量。以乙個協議包 5 個位元組計算,一天收發 2880 個心跳包,乙個月就是 5 * 2 * 2880 * 30 = 0.8 m 的流量,如果手機上多裝幾個 im 軟體,每個月光心跳就好幾兆流量沒了,更不用說頻繁的心跳帶來的電量損耗。

以上就是網易雲信對於心跳指令的理解和實踐,《移動im開發指南》第三篇文章將為大家介紹如何優化登入模組,敬請期待。

移動 IM 開發之心跳

什麼是心跳?在使用 tcp 長連線的im 服務設計中,往往都會涉及到心跳。心跳一般是指某端 絕大多數情況下是客戶端 每隔一定時間向對端傳送自定義指令,以判斷雙方是否存活,因其按照一定間隔傳送,類似於心跳,故被稱為心跳指令。為什麼要在應用層做心跳 那麼問題就隨之而來了 為什麼需要在應用層做心跳,難道 ...

移動IM開發指南3 如何優化登入模組

推薦閱讀 移動im開發指南1 如何進行技術選型 移動im開發指南2 心跳指令詳解 在移動 im 模組中,最核心最複雜的模組莫過於登入模組。乙個沒有經過很好優化的登入模組往往耗時久且浪費流量 一次登入短則數十秒,長則幾分鐘,同時同步下幾百 kb 甚至幾m的資料。乙個簡單的登入步驟可以分為如下幾步 l ...

移動IM開發指南1 如何進行技術選型

移動im開發指南2 心跳指令詳解 移動im開發指南3 如何優化登入模組 im通訊方式無非兩種選擇 裝置直連 p2p 和通過伺服器中轉 1.p2p p2p多見於區域網內聊天工具,典型的應用有 飛鴿傳書等。這類軟體在啟動後一般做兩件事情 2.伺服器中轉 幾乎所有網際網路im產品都採用伺服器中轉這種方式進...