TCP系列37—Keep Alive—1、TCP存活檢測


一、TCP存活(keepalive)檢測的背景

        對於TCP設計來說,如果一個客戶端和服務器端建立連接后,不在進行數據傳輸,那么這個連接將會一直存在下去,理論上即使中間的路由器崩潰重啟、或者中間的網絡線路拔掉在插上等等,只要客戶端和服務器端的主機沒有發生異常,這個TCP連接仍然是處於連接狀態的。這樣會有兩個問題

1、服務器端可能需要內存等資源保存每個連接的狀態信息,即使這個連接在實際上已經不能通信而沒有存在的必要了。比如客戶端崩潰時,服務器可能仍然認為這個連接是有效的而繼續占用為這個連接分配的資源

2、防火牆和NAT設備可能會保存一個連接超時的定時器,如果這個TCP連接長時間沒有數據傳輸,定時器超時后,服務器端和客戶端實際上已經不能在進行通信。

為了解決上面的兩個問題,TCP連接需要一個存活(keepalive)檢測機制,定時檢測當前的TCP連接是否可用,以刷新防火牆和NAT信息,或者當檢測到連接失敗的時候釋放相關資源。


二、存活檢測的兩種方式:

1、應用層面的心跳機制(application-managed keepalive)

自定義心跳消息頭. 一般客戶端主動發送, 服務器接收后進行回應(也可以不回應)。相比傳輸層的keepalive檢測,應用層的檢測更靈活且不依賴傳輸層的協議。 例如最新的ssh就有應用層的存活檢測機制。本文不做額外介紹。

2、傳輸層的存活檢測

TCP的存活檢測就屬於傳輸層的存活檢測功能,相比於應用層的檢測,傳輸層的檢測可以提供更通用的檢測從而減少應用層的工作量,另外傳輸層的探測包不需要添加應用層的頭,從而減輕了網絡負載。傳輸層的TCP keepalive是接下來介紹的功能。


三、TCP的存活檢測

        TCP keealive定義於RFC1122,但是並不是要求每個TCP實現都支持keepalive,[RFC1122]給出的原因是(1)在短暫的故障期間,它們可能引起一個良好連接被釋放,比如網絡中間的路由器崩潰了並且正在重啟,keepalive檢測可能會認為對端主機崩潰而釋放連接,實際上在這種情況下路由器重啟完畢后,該TCP連接可以繼續通信;(2)需要消耗額外的帶寬資源;(3)在以數據包計費的互聯網上需要額外花費金錢;但是盡管如此,很多TCP實現還是支持TCP的存活檢測。

3.1、TCP存活檢測的機制

        TCP的存活檢測可以在TCP連接的兩端同時啟用,或者只在一端啟用,或者兩端都不啟用。在TCP的存活檢測中有三個參數

keepalive time:存活檢測時間間隔

keepalive interval:沒有收到ACK響應時存活檢測時間間隔

keepalive probes:沒有收到ACK響應時存活檢測累計次數,因為keepalive依靠探測包的ACK響應判斷連接情況,但是不攜帶數據的ACK沒有重傳不是可靠的傳輸,因此需要多次累計探測沒有響應才能認為連接失活。

        TCP的存活檢測流程如下:在TCP存活檢測中有一個存活定時器(keepalive timer),當TCP連接的任何一個方向有業務數據傳輸時就會把這個存活定時器重置為keepalive time,當沒有數據傳輸本端這個定時器超時的時候,TCP就會發送一個探測包(keepalive probe 或者簡稱為keepalive包),對端接收到這個探測包后就會響應一個ACK,本端接收到這個ACK響應的時候就會重置這個存活定時器為keepalive time。如果本端沒有收到這個ACK響應,會以keepalive interval為間隔時間重復發送探測包,如果一直發送了keepalive probes次都沒有收到ACK響應,則認為這個連接已經失活。如果中間的某次收到ACK響應則會重置存活定時器為keepalive time,並且停止keepalive interval為間隔的探測包重復發送。


3.2、探測包的包格式

        對於探測包的格式,一般是使用本端目前發送窗口的上一個byte做為系列號,比如當前本端接受到的最大連續ACK Number為n,則探測包的seq為n-1;按照RFC1122,探測包中可以不包含數據,也可以包含1byte的無用數據(garbage byte)以兼容老式TCP實現。


3.3、TCP存活檢測可以檢測到的連接情況

TCP的存活檢測可以檢測到四種連接情況,在下面的描述中,我們稱使用存活選項的那一段為服務器,另一端為客戶端。也可以在客戶端設置該選項,且沒有不允許這樣做的理由,但通常設置在服務器。如果連接兩端都需要探測對方是否消失,那么就可以在兩端同時設置(比如NFS)。

1)客戶端主機依舊活躍(up)運行,並且從服務器可到達。從客戶端TCP的正常響應,服務器知道對方仍然活躍。服務器的TCP復位存活定時器為keepalive time,如果在keepalive time到期之前,連接上發生應用程序的通信,則TCP會將存活定時器重置為keepalive time。

2) 客戶端已經崩潰,或者已經關閉(down),或者正在重啟過程中。在這兩種情況下,它的TCP都不會響應。服務器沒有收到對其發出探測的響應,並且在keepalive interval秒之后超時。服務器將總共發送keepalive probes個這樣的探測,每個探測間隔keepalive interval秒。如果沒有收到一個響應,它就認為客戶端主機已經關閉並終止連接。

3) 客戶端曾經崩潰,但已經重啟。這種情況下,服務器將會收到對其存活探測的響應,但該響應是一個復位(在TCP頭中置位RST標識),從而引起服務器對連接的終止。

4) 客戶端主機活躍運行,但從服務器不可到達。這與狀態2類似(但是狀態4可能會收到ICMP的錯誤指示信息),因為TCP無法區別它們兩個。它所能表明的僅是未收到對其探測的回復。

服務器不必擔心客戶端主機被關閉然后重啟的情況(這里指的是操作員執行的 正常關閉,而不是主機的崩潰)。當系統被操作員關閉時,所有的應用程序進程(也就是客戶端進程)都將被終止,客戶端TCP會在連接上發送一個FIN。收到 這個FIN后,服務器TCP向服務器進程報告一個文件結束,以允許服務器檢測這種狀態。

在第一種狀態下,服務器應用程序不知道存活探測是否發生。凡事都是由 TCP層處理的,存活探測對應用程序透明,直到后面2,3,4三種狀態發生。在這三種狀態下,通過服務器的TCP,返回給服務器應用程序錯誤信息。(通常 服務器向網絡發出一個讀請求,等待客戶端的數據。如果存活檢測返回一個錯誤信息,則將該信息作為讀操作的返回值返回給服務器。)在狀態2,錯誤信息類似於 “連接超時”。狀態3則為“連接被對方復位”。第四種狀態看起來像連接超時,或者根據是否收到與該連接相關的ICMP錯誤信息,而可能返回其它的錯誤信息。


四、TCP存活檢測的相關參數設置

在各個系統下三個參數對應如下表,括號中給出的是系統的默認值,其中keepalive probs參數在FreeBSD和Mac OS X下為常量。另外在FreeBSD和Mac OS X這兩個系統下還有一個net.inet.tcp.always_keepalive的布爾變量,如果這個變量使能,則所有的TCP連接都會有keepalive功能,即使應用程序沒有請求keepalive功能(Linux通過libkeepalive庫也可以實現相似功能)。其中Windows系統下的參數在注冊表[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]下


keepalive time keepalive interval keepalive probs
Linxu net.ipv4.tcp_keepalive_time(7200) net.ipv4.tcp_keepalive_intvl(75) net.ipv4.tcp_keepalive_probes(9)
FreeBSD net.inet.tcp.keepidle(7200) net.inet.tcp.keepintvl(75) 8
Mac OS X net.inet.tcp.keepidle(7200) net.inet.tcp.keepintvl(75) 9
Windows KeepAliveTime(7200) KeepAliveInterval(1) MaxDataRetries(5)

RFC1122中規定keepalive time默認不能少於2小時,另外keepalive功能必須默認關閉,除非應用程序請求使用keepalive功能(FreeBSD和Mac OS X系統下net.inet.tcp.always_keepalive設置是違反這個行為的)。


五、wireshark示例

1、通過linux的socket選項,設置keepalive time=5s、keepalive interval=1s、keepalive probes=3。最終如下圖所示

client在與server端建立連接后,雙發並沒有數據進行傳輸,server每隔5s進行一次keepalive探測,但是No10探測包沒有收到client的回復,因此server端又隔了1s重復進行探測,最終發送了三個探測包No10、No11、No12后,server端放棄探測,認定與client端的連接已經斷開,因此最后發送一個RST報文后,server端也會釋放這個連接。








免責聲明!

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



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