網(wǎng)絡編程-為什么需要應用層做心跳處理?
背景
許多小伙伴做網(wǎng)絡編程時,會自然而然的去做應用層的心跳檢測機制,如果問為什么要做心跳檢測,大部分人會說保活,及時發(fā)現(xiàn)連接失效等等。這篇文章會結合TCP協(xié)議原理來分析,使用應用層做心跳檢測的原因和必要性。
沒有應用層心跳檢測時
在沒有應用層心跳檢測時,我們如何發(fā)現(xiàn)對端應用程序崩潰/對端主機崩潰/主機不可達等等異常呢?
假如網(wǎng)絡正常
我們考慮異常時在發(fā)送數(shù)據(jù)包:
- 如果對端程序崩潰還未重啟,會發(fā)送FIN,本端可以立即感知
- 如果對端 程序崩潰/主機崩潰 后已經(jīng)重啟,會發(fā)送RST,本端可以立即感知
- 對端主機崩潰一直未重啟,我們發(fā)送的數(shù)據(jù)包將會TCP超時
- 對端主機不可達,我們發(fā)送的數(shù)據(jù)包將會TCP超時
TCP超時重傳的默認機制是什么呢?
首先明確,超時重傳的原理是在發(fā)送某一個數(shù)據(jù)以后就開啟一個計時器,在一定時間內如果沒有得到發(fā)送的數(shù)據(jù)報的ACK報文,那么就重新發(fā)送數(shù)據(jù),直到發(fā)送成功為止。
關于超時重傳的時間間隔和重傳次數(shù),下面這篇博客比較詳細的講解了這個知識點:TCP/IP重傳超時--RTO
總結一下博客中的內容
- RTO有一個最小值,不同內核中是寫死的,博客中提到的內核版本是200ms,就算RTT是0.5ms也不行的,會用200ms來發(fā)送第二次發(fā)送的數(shù)據(jù)包。
- TCP內核中可以修改兩個參數(shù)
/proc/sys/net/ipv4/tcp_retries1 (integer; default: 3)
TCP嘗試了3次(tcp_retries1默認3)重傳后,還沒有收到ACK的話,則后續(xù)每次重傳都需要network layer先更新路由。
/proc/sys/net/ipv4/tcp_retries2 (integer; default: 15)
TCP默認最多做15次重傳。根據(jù)RTO(retransmission timeout)不同,最后一次重傳間隔大概是13到30分鐘左右。如果15次重傳都做完了,TCP/IP就會告訴應用層說:“搞不定了,包怎么都傳不過去!”
如果沒有應用層心跳檢測,我們發(fā)送的數(shù)據(jù)包,最差需要依靠TCP超時來判斷對端出現(xiàn)問題,這個超時時間是很長的,在現(xiàn)代的業(yè)務中幾乎無法滿足業(yè)務的需求。
我們考慮只接收對端數(shù)據(jù)包的過程:
- 如果對端程序崩潰,會發(fā)送FIN,本端可以立即感知
- 對端主機崩潰
- 如果關閉了Tcp的KeepAlive保活機制,那么沒有任何感知;
- 如果開啟了TCP keep_alive,會通過保活機制,發(fā)送幾個檢測包,要么超時,要么得到RST
- 對端主機不可達,和上面的主機崩潰同理
如果沒有應用層心跳檢測,我們在不發(fā)送,只接受的情況下,最差需要依靠Keep Alive機制的超時或RST來判斷對端出現(xiàn)問題,超時時間為:2小時+75秒* 9次。這個時間在默認參數(shù)設置下也是很長的。另外,這三個參數(shù)也可以修改的:
net.ipv4.tcp_keepalive_time 對應2小時
net.ipv4.tcp_keepalive_intvl 對應75秒
net.ipv4.tcp_keepalve_probes 對應9次
假如網(wǎng)絡異常
假如有網(wǎng)絡異常,但是對方主機和程序都正常
發(fā)送數(shù)據(jù)包時:
- 通過本端TCP超時,發(fā)現(xiàn)網(wǎng)絡異常
接收數(shù)據(jù)包時:
- 通過Keep_Alive機制來探測
有應用層心跳檢測時
通過上面的分析可以得知,對于網(wǎng)絡應用,無論是依賴TCP超時還是Keep Alive,在最差的情況下的超時時間都是不可接受的。所以我們需要在應用層做一個類似的心跳檢測機制,保證可以在任何情況下都可以快速的檢測出異常情況。
那么是否可以只發(fā)一次,在規(guī)定時間內沒收到回復就判定連接異常呢?考慮下面的兩種情況:
- 網(wǎng)絡波動,但是對端主機和服務都正常
- 對端主機正忙于處理其他事務,響應慢了一些
對這兩種情況來說,如果檢測一次,發(fā)現(xiàn)超時就判定連接失效基本屬于誤傷,可以通過多發(fā)送幾次心跳檢測包來規(guī)避上面的誤傷情況。
并且還需要考慮,在多次發(fā)送的心跳包,需要帶序號,對端回復時,也要保證使用這個序號或者序號+1來匹配我們發(fā)出去的心跳包。如果編號對應不上,就不能算作此次檢測成功了。

浙公網(wǎng)安備 33010602011771號