TCP 連接斷鏈分析
在官方的正式文檔中,TCP/IP 協(xié)議簇也稱為國際互聯(lián)網(wǎng)協(xié)議簇。TCP/IP 協(xié)議簇是目前使用最為廣泛的全球互聯(lián)網(wǎng)技術(shù),其分層結(jié)構(gòu)如圖 1 所示:
圖 1. TCP/IP 協(xié)議簇分層結(jié)構(gòu)
如圖 1 所示,數(shù)據(jù)鏈路層主要負責處理傳輸媒介等眾多的物理接口細節(jié);網(wǎng)絡層負責處理數(shù)據(jù)分組在網(wǎng)絡中的活動,包括上層數(shù)據(jù)報文的分割、選路 phost2008-08-21T00:00:00 等;傳輸層則負責為兩臺主機提供端到端的通信;應用層將負責處理應用程序的特定細節(jié)。其中,IP 協(xié)議是網(wǎng)絡層的核心協(xié)議,用來提供不可靠、無連接的數(shù)據(jù)傳遞服務;而 TCP 協(xié)議則處于傳輸層,其基于不可靠無連接的 IP 協(xié)議能夠為兩臺主機提供面向連接的、可靠的通信。UDP?
由于 TCP 是面向連接的協(xié)議,因此在兩臺主機通信之前,需要首先建立起一條連接。下面我們將簡要介紹 TCP 連接的建立以及通信雙方是如何保持已建立的 TCP 連接的。
TCP 連接的建立及保持
一個 TCP 連接的建立需要通過著名的“三次握手”來完成。下面的例子將直觀給出一個 TCP 連接的建立過程。
在本文的下述描述中,客戶端主機均為 testClient.cn.ibm.com(Linux),服務器主機均為 testServer.cn.ibm.com(AIX)。在 testClient 主機的一終端上執(zhí)行 tcpdump –i eth0 host testServer 命令,啟動 tcpdump 監(jiān)聽網(wǎng)絡數(shù)據(jù)(其中,eth0 是客戶主機與外部網(wǎng)絡進行通信所使用的網(wǎng)卡);與此同時,在客戶主機的另一個終端上執(zhí)行下述命令: (root@testClient /)》telnet testServer。此時客戶主機上 tcpdump 的輸出如清單 1 所示。
清單 1. 創(chuàng)建一個 TCP 連接的三次握手
# tcpdump –S -i en0 host testServer
1 14:02:38.384918 IP testClient.cn.ibm.com.43370 》
testServer.cn.ibm.com.telnet: S 3392458353:3392458353(0) …
2 14:02:38.629578 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.43370: S 881279296:881279296(0) ack 3392458354 …
3 14:02:38.629592 IP testClient.cn.ibm.com.43370 》
testServer.cn.ibm.com.telnet: 。 ack 881279297 …
注意:我們刪除了 tcpdump 輸出結(jié)果中的部分無關(guān)信息。為了便于理解,我們將上述輸出轉(zhuǎn)換為實際序列圖 2。
圖 2. TCP 建立創(chuàng)建三次握手的實際序列
從圖 2 中我們可以清楚地看到,在 testClient 與 testServer 之間建立連接時,要經(jīng)過以下三次握手過程:
testClient 向 testServer 主動發(fā)送握手協(xié)議,報文序列號為 3392458353,大小為 1 個字節(jié)。
testServer 向 testClient 主動發(fā)送握手協(xié)議,報文序列號為 881279296,大小為 1 個字節(jié);同時返回 ACK 3392458354,作為對 testClient 發(fā)來的 3392458354 包的應答。
testClient 向 testServer 返回 ACK 881279297,作為對 testServer 發(fā)來的 881279296 包的應答。
一個 TCP 連接在完成上述的三次握手之后便建立完畢;此后,連接的兩端即可進行信息的相互傳遞。因此,TCP 連接可以認為是以兩端 IP 地址和端口進行標識的一個通信信道,而 TCP 連接的建立就是向通信雙方進行上述通信信道注冊的過程。TCP 連接一旦建立,只要通信雙方之間的中間結(jié)點(包括網(wǎng)關(guān)和交換機、路由器等網(wǎng)絡設備)工作正常,那么在通信雙方中的任何一方主動關(guān)閉連接之前,TCP 連接都將被一直保持下去。
TCP 連接的這種特性,使得一個長期不交換任何信息的空閑連接可以長期保持數(shù)小時、數(shù)天甚至數(shù)月。中間路由器可以崩潰、重啟,網(wǎng)線可以被掛斷再連通,只要兩端的主機沒有被重啟,TCP 連接就可以被一直保持下來。
導致 TCP 連接斷連的因素
理想狀態(tài)下,一個 TCP 連接可以被長期保持。然而,在實際應用中,客戶端或服務器端上維持的一個看似正常的 TCP 連接可能已經(jīng)斷連。TCP 連接主要受到兩個方面的影響而導致斷連:網(wǎng)絡中間節(jié)點和客戶端 / 服務器節(jié)點參與通信的兩方節(jié)點?
在實際網(wǎng)絡應用中,兩個主機之間的通信往往需要穿越多個中間節(jié)點,例如路由器、網(wǎng)關(guān)、防火墻等。因此,兩個主機之間 TCP 連接的保持同樣會受到中間節(jié)點的影響,尤其是會受到防火墻(軟件或硬件防火墻)的限制。防火墻是一種裝置,有多種不同的實現(xiàn)方式(軟件實現(xiàn)、硬件設備實現(xiàn) 或是軟硬件相結(jié)合實現(xiàn)),它需要依據(jù)一系列規(guī)則對進出的信息流進行掃描,并允許安全(符合規(guī)則)的信息交互、阻止不安全(違反規(guī)則)的信息交互。防火墻的 工作特性決定了要維護一個網(wǎng)絡連接就需要耗費較多的資源,并且企業(yè)防火墻常常位于企業(yè)網(wǎng)絡的出入口,長時間維護非活躍的 TCP 連接必將導致網(wǎng)絡性能的下降。因此,大部分防火墻默認會關(guān)閉長時間處于非活躍狀態(tài)的連接而導致 TCP 連接斷連。類似的,如果中間節(jié)點異常導致來自客戶端關(guān)閉連接的請求無法傳遞到服務器端,也將導致服務器端的相應連接發(fā)生斷連。
另一方面,對于一個 TCP 連接兩端的主機而言,創(chuàng)建 TCP 連接需要耗費一定的系統(tǒng)資源。如果不再使用某個連接,那么我們總是希望進行通信的兩個主機能夠主動關(guān)閉相應的連接,以便釋放所占用的系統(tǒng)資源。然而,如果 由于客戶端出現(xiàn)異常 ( 例如崩潰或異常重啟 ) 而導致連接未能正常關(guān)閉,這將導致服務器端的連接斷連。
無論是客戶端節(jié)點或是服務器端節(jié)點,斷連的 TCP 連接已經(jīng)不能傳遞任何信息,因此,維護大量斷連的 TCP 連接將導致系統(tǒng)資源的浪費。這種系統(tǒng)資源的浪費可能并不會對客戶端節(jié)點帶來太大問題;然而,對于服務器主機而言,這可能會導致系統(tǒng)資源(尤指內(nèi)存資源和 socket 資源)被耗盡而拒絕為新的用戶請求提供服務。因此在實際應用中,服務器端需要采取相應的方法來探測 TCP 連接是否已經(jīng)斷連。
探測 TCP 連接斷連的三種常用方法
探測 TCP 連接是否斷連或是工作正常的原理比較簡單:定期向連接的遠程通信節(jié)點發(fā)送一定格式的信息并等待遠程通信節(jié)點的反饋,如果在規(guī)定時間內(nèi)收到來自遠程節(jié)點的正 確的反饋信息,那么該連接就是正常的,否則該連接已經(jīng)斷連。依據(jù)該原理,目前常用的探測方法有以下三種。
應用程序的自我探測
應用程序本身附帶探測其自身建立的 TCP 連接的功能。這種方法具有極大的靈活性,可以依據(jù)應用本身的特點選擇相應的探測機制和功能實現(xiàn)。然而,實際應用中,大部分應用程序均沒有附帶自我探測的功能。
第三方應用程序的探測
此種方法就是在服務節(jié)點上安裝相應的第三方應用程序來探測該節(jié)點上所有的 TCP 連接是否正常或是已經(jīng)斷連。該方法最大的不足就是需要所有支持探測的客戶端能夠識別來自該探測應用的數(shù)據(jù)報文,因此,實際應用中比較少見。
TCP 協(xié)議層的保活探測
最常用的探測方法就是采用 TCP 協(xié)議層提供的保活探測功能即 TCP 連接保活定時器。盡管該功能并不是 RFC 規(guī)范的一部分,但是幾乎所有的類 Unix 系統(tǒng)均實現(xiàn)了該功能,所以使得該探測方法被廣泛使用。
接下來的部分,我們將重點討論來自 TCP 協(xié)議層的保活探測方法。
類 Unix 系統(tǒng)上的 TCP 連接保活定時器
TCP 連接的保活定時器可以在應用層實現(xiàn),也可以在 TCP 中提供。這個問題存在爭議,因此 TCP 連接的保活探測并不是 TCP 規(guī)范中的一部分。但為了方便,幾乎所有類 Unix 系統(tǒng)均在 TCP 中提供了相應的功能。
清單 2. 常見 Unix 系統(tǒng)上的保活定時器
操作系統(tǒng) 保活定時器
AIX# no -a | grep keep
tcp_keepcnt = 8
tcp_keepidle = 14400
tcp_keepintvl = 150
Linux# sysctl -A | grep keep
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
FreeBSD#sysctl -A | grep net.inet.tcp
net.inet.tcp.keepidle=…
net.inet.tcp.keepintvl=…
不同系統(tǒng)上的各參數(shù)的時間單位不盡相同。在 AIX 上,tcp_keeidle/tcp_keepinit/tcp_keepintvl 的時間單位是 0.5 秒;而在 Linux 上,net.ipv4.tcp_keepalive_intvl 和 net.ipv4.tcp_keepalive_time 的時間單位則為秒。并且,上述參數(shù)僅對運行在其上的服務器應用連接有效。
注:在 Solaris 上可通過“ndd /dev/tcp \?”命令顯示上述類似參數(shù)信息,而在 HP Unix 上則可通過 nettune 或 ndd 命令進行查詢。
由于所有類 Unix 系統(tǒng)上均支持這種功能,因此,在接下來的部分中我們將基于 AIX 系統(tǒng)具體講述上述參數(shù)的意義和作用機制。
AIX 中的 TCP 連接保活探測機制及原理
正如清單 2 中列出的一樣,AIX 上的保活探測機制由 4 個參數(shù)來控制,其具體意義見清單 3:
清單 3. AIX 上的保活定時器控制參數(shù)
評論
查看更多