網(wǎng)絡(luò)編程-為什么需要應(yīng)用層做心跳處理?

背景

許多小伙伴做網(wǎng)絡(luò)編程時(shí),會自然而然的去做應(yīng)用層的心跳檢測機(jī)制,如果問為什么要做心跳檢測,大部分人會說?;?,及時(shí)發(fā)現(xiàn)連接失效等等。這篇文章會結(jié)合TCP協(xié)議原理來分析,使用應(yīng)用層做心跳檢測的原因和必要性。

沒有應(yīng)用層心跳檢測時(shí)

在沒有應(yīng)用層心跳檢測時(shí),我們?nèi)绾伟l(fā)現(xiàn)對端應(yīng)用程序崩潰/對端主機(jī)崩潰/主機(jī)不可達(dá)等等異常呢?

假如網(wǎng)絡(luò)正常
我們考慮異常時(shí)在發(fā)送數(shù)據(jù)包:
  • 如果對端程序崩潰還未重啟,會發(fā)送FIN,本端可以立即感知
  • 如果對端 程序崩潰/主機(jī)崩潰 后已經(jīng)重啟,會發(fā)送RST,本端可以立即感知
  • 對端主機(jī)崩潰一直未重啟,我們發(fā)送的數(shù)據(jù)包將會TCP超時(shí)
  • 對端主機(jī)不可達(dá),我們發(fā)送的數(shù)據(jù)包將會TCP超時(shí)

TCP超時(shí)重傳的默認(rèn)機(jī)制是什么呢?

首先明確,超時(shí)重傳的原理是在發(fā)送某一個(gè)數(shù)據(jù)以后就開啟一個(gè)計(jì)時(shí)器,在一定時(shí)間內(nèi)如果沒有得到發(fā)送的數(shù)據(jù)報(bào)的ACK報(bào)文,那么就重新發(fā)送數(shù)據(jù),直到發(fā)送成功為止。

關(guān)于超時(shí)重傳的時(shí)間間隔和重傳次數(shù),下面這篇博客比較詳細(xì)的講解了這個(gè)知識點(diǎn):TCP/IP重傳超時(shí)--RTO

總結(jié)一下博客中的內(nèi)容

  1. RTO有一個(gè)最小值,不同內(nèi)核中是寫死的,博客中提到的內(nèi)核版本是200ms,就算RTT是0.5ms也不行的,會用200ms來發(fā)送第二次發(fā)送的數(shù)據(jù)包。
  2. TCP內(nèi)核中可以修改兩個(gè)參數(shù)
/proc/sys/net/ipv4/tcp_retries1 (integer; default: 3)
TCP嘗試了3次(tcp_retries1默認(rèn)3)重傳后,還沒有收到ACK的話,則后續(xù)每次重傳都需要network layer先更新路由。

/proc/sys/net/ipv4/tcp_retries2 (integer; default: 15)
TCP默認(rèn)最多做15次重傳。根據(jù)RTO(retransmission timeout)不同,最后一次重傳間隔大概是13到30分鐘左右。如果15次重傳都做完了,TCP/IP就會告訴應(yīng)用層說:“搞不定了,包怎么都傳不過去!”

如果沒有應(yīng)用層心跳檢測,我們發(fā)送的數(shù)據(jù)包,最差需要依靠TCP超時(shí)來判斷對端出現(xiàn)問題,這個(gè)超時(shí)時(shí)間是很長的,在現(xiàn)代的業(yè)務(wù)中幾乎無法滿足業(yè)務(wù)的需求。

我們考慮只接收對端數(shù)據(jù)包的過程:
  • 如果對端程序崩潰,會發(fā)送FIN,本端可以立即感知
  • 對端主機(jī)崩潰
    • 如果關(guān)閉了Tcp的KeepAlive?;顧C(jī)制,那么沒有任何感知;
    • 如果開啟了TCP keep_alive,會通過?;顧C(jī)制,發(fā)送幾個(gè)檢測包,要么超時(shí),要么得到RST
  • 對端主機(jī)不可達(dá),和上面的主機(jī)崩潰同理

如果沒有應(yīng)用層心跳檢測,我們在不發(fā)送,只接受的情況下,最差需要依靠Keep Alive機(jī)制的超時(shí)或RST來判斷對端出現(xiàn)問題,超時(shí)時(shí)間為:2小時(shí)+75秒* 9次。這個(gè)時(shí)間在默認(rèn)參數(shù)設(shè)置下也是很長的。另外,這三個(gè)參數(shù)也可以修改的:

net.ipv4.tcp_keepalive_time 對應(yīng)2小時(shí)
net.ipv4.tcp_keepalive_intvl 對應(yīng)75秒
net.ipv4.tcp_keepalve_probes 對應(yīng)9次
假如網(wǎng)絡(luò)異常

假如有網(wǎng)絡(luò)異常,但是對方主機(jī)和程序都正常

發(fā)送數(shù)據(jù)包時(shí):

  • 通過本端TCP超時(shí),發(fā)現(xiàn)網(wǎng)絡(luò)異常

接收數(shù)據(jù)包時(shí):

  • 通過Keep_Alive機(jī)制來探測

有應(yīng)用層心跳檢測時(shí)

通過上面的分析可以得知,對于網(wǎng)絡(luò)應(yīng)用,無論是依賴TCP超時(shí)還是Keep Alive,在最差的情況下的超時(shí)時(shí)間都是不可接受的。所以我們需要在應(yīng)用層做一個(gè)類似的心跳檢測機(jī)制,保證可以在任何情況下都可以快速的檢測出異常情況。

那么是否可以只發(fā)一次,在規(guī)定時(shí)間內(nèi)沒收到回復(fù)就判定連接異常呢?考慮下面的兩種情況:

  • 網(wǎng)絡(luò)波動(dòng),但是對端主機(jī)和服務(wù)都正常
  • 對端主機(jī)正忙于處理其他事務(wù),響應(yīng)慢了一些

對這兩種情況來說,如果檢測一次,發(fā)現(xiàn)超時(shí)就判定連接失效基本屬于誤傷,可以通過多發(fā)送幾次心跳檢測包來規(guī)避上面的誤傷情況。

并且還需要考慮,在多次發(fā)送的心跳包,需要帶序號,對端回復(fù)時(shí),也要保證使用這個(gè)序號或者序號+1來匹配我們發(fā)出去的心跳包。如果編號對應(yīng)不上,就不能算作此次檢測成功了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容