博主聯系方式:
QQ:1540984562
微信:wxid_nz49532kbh9u22
QQ交流群:750313950(嵌入式方向)
QQ交流群:856398158(后端方向)
目錄
- 心跳檢測應用場景
- 死連接情況
- 保活
- 傳遞有效業務數據
- 心跳包機制設計
- 通用心跳包設計
- 有代理的心跳包設計
心跳檢測應用場景
心跳檢測一般有兩個作用:保活和檢測死連接。
死連接情況
服務器與客戶端不在一個網絡中,之間的數據會經過多個路由器和交換機,如果其中某個必經之路的機器出現了故障,并且在一段時間內沒有恢復,則會導致這之間的鏈路不再通暢,此時服務器和客戶端之間沒有數據交換。并且由于TCP連接是狀態機,所以對于這種情況,通信兩方是無法感知與對方的連接是否正常。又如果客戶端因為網絡原因或者崩潰等許多原因斷開了與服務端的連接,然而服務端卻不知道客戶端已經斷開了連接并等待客戶端給他發送數據占用著系統資源,我們稱這樣的情況為“死連接”。
在這個情況中,我們只要在服務端向客戶端發送一個數據包,即可檢測連接是否正常,這類數據包稱為心跳包,這種操作稱為心跳檢測。如果一個連接長時間沒有正常數據來往,有沒有心跳包來往,就可以認為這個連接已經不存在了,此時應該關閉socket來回收連接資源。
保活
一個客戶端在連接服務器之后,如果長時間沒有和服務器有數據來往,可能會被防火墻程序關閉連接,但是有時我們希望這個連接保持下去。因為對于即時通信來說,服務器沒有消息時,確實不會有數據交換,但是連接關閉的話,新消息到來的話就無法接受到了。這種情況,我們只需要向對方發送心跳包即可實現保活。
傳遞有效業務數據
實際應用中,有時需要定時或者不定時地從服務端更新一些數據,可以把這類數據放在心跳包中,定時或者不定時更新。
但是對于連接數較多時,為了減輕網絡帶寬和流量,設計心跳包數據格式時應該盡量減少心跳包大小。
心跳包機制設計
通用心跳包設計
心跳包其實就是一個預先設置好格式的數據包,在程序中啟動一個定時器定時發送即可。
但是如果通信兩端有頻繁的業務數據來往,此時這些數據包本身就可以起到保活的作用,就沒有必要浪費流量發送心跳包了。
最佳的做法就是記錄最近一次收發數據包的時間,在每次收數據和發送數據的時候就更新這個時間。而心跳檢測的計時器在每次檢測時都將這個時間與當前的系統時間做比較,如果時間間隔大于允許的最大間隔,則發送一次心跳包。
簡而言之:在與對端之間沒有數據來往達到一定時間間隔時,才發送一次心跳包。
同時檢測心跳包的一方,應該是在與對端沒有數據來往達到一定時間間隔時才做一次心跳檢測。
一般來說是客戶端主動向服務端發送心跳包,服務端做心跳檢測來決定是否斷開連接。從客戶端的角度來說,客戶端為了讓自己得到服務端的正常服務,有必要主動和服務端保持正常連接。服務端在收到客戶端的心跳包時,應該給客戶端一個心跳應答。
有代理的心跳包設計
在后端服務程序與客戶端之間存在代理服務時,后端服務與代理服務之間是長連接,代理服務與客戶端之間也是長連接。
后端服務器的業務類型是訂閱類型,客戶端一旦訂閱某個類型的主題,就很少或者不再發送數據給服務器了,服務器會將被訂閱的數據下發到代理服務器,然后客戶端從代理服務器獲取數據。
現在有一個情況:客戶端和代理服務之間的連接斷開,代理服務和后端服務的連接正常。此時后端服務的下行數據會一直暢通,但此時客戶端與代理服務可能已經斷開好一會兒了。此時后端服務會根據下行數據更新最后一次心跳時間,所以會導致心跳檢測誤判后端程序與客戶端的連接狀態。因為這里我們使用的方法仍然是檢測后端服務更新心跳包時間。
此時只需要更改機制為:只通過后端服務的上行數據來更新時間戳,若超過某段時間后仍然沒有上行數據,則說明客戶端已經斷開了(這段時間內,服務端既沒有收到客戶端的業務數據包,也沒有收到客戶端的心跳數據包)