網絡編程-為什么需要應用層做心跳處理?


背景

許多小伙伴做網絡編程時,會自然而然的去做應用層的心跳檢測機制,如果問為什么要做心跳檢測,大部分人會說保活,及時發現連接失效等等。這篇文章會結合TCP協議原理來分析,使用應用層做心跳檢測的原因和必要性。

沒有應用層心跳檢測時

在沒有應用層心跳檢測時,我們如何發現對端應用程序崩潰/對端主機崩潰/主機不可達等等異常呢?

假如網絡正常
我們考慮異常時在發送數據包:
  • 如果對端程序崩潰還未重啟,會發送FIN,本端可以立即感知
  • 如果對端 程序崩潰/主機崩潰 后已經重啟,會發送RST,本端可以立即感知
  • 對端主機崩潰一直未重啟,我們發送的數據包將會TCP超時
  • 對端主機不可達,我們發送的數據包將會TCP超時

TCP超時重傳的默認機制是什么呢?

首先明確,超時重傳的原理是在發送某一個數據以后就開啟一個計時器,在一定時間內如果沒有得到發送的數據報的ACK報文,那么就重新發送數據,直到發送成功為止。

關於超時重傳的時間間隔和重傳次數,下面這篇博客比較詳細的講解了這個知識點:TCP/IP重傳超時--RTO

總結一下博客中的內容

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

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

如果沒有應用層心跳檢測,我們發送的數據包,最差需要依靠TCP超時來判斷對端出現問題,這個超時時間是很長的,在現代的業務中幾乎無法滿足業務的需求。

我們考慮只接收對端數據包的過程:
  • 如果對端程序崩潰,會發送FIN,本端可以立即感知
  • 對端主機崩潰
    • 如果關閉了Tcp的KeepAlive保活機制,那么沒有任何感知;
    • 如果開啟了TCP keep_alive,會通過保活機制,發送幾個檢測包,要么超時,要么得到RST
  • 對端主機不可達,和上面的主機崩潰同理

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

net.ipv4.tcp_keepalive_time 對應2小時
net.ipv4.tcp_keepalive_intvl 對應75秒
net.ipv4.tcp_keepalve_probes 對應9次
假如網絡異常

假如有網絡異常,但是對方主機和程序都正常

發送數據包時:

  • 通過本端TCP超時,發現網絡異常

接收數據包時:

  • 通過Keep_Alive機制來探測

有應用層心跳檢測時

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

那么是否可以只發一次,在規定時間內沒收到回復就判定連接異常呢?考慮下面的兩種情況:

  • 網絡波動,但是對端主機和服務都正常
  • 對端主機正忙於處理其他事務,響應慢了一些

對這兩種情況來說,如果檢測一次,發現超時就判定連接失效基本屬於誤傷,可以通過多發送幾次心跳檢測包來規避上面的誤傷情況。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM