互聯(lián)網(wǎng)是人類歷史上最偉大的發(fā)明創(chuàng)造之一,,而構成互聯(lián)網(wǎng)架構的核心在于TCP/IP協(xié)議。那么TCP/IP是如何工作的呢,,我們先從數(shù)據(jù)包開始講起,。 1、數(shù)據(jù)包 一,、HTTP請求和響應步驟 http請求全過程 請求 響應 以上完整表示了HTTP請求和響應的7個步驟,,下面從TCP/IP協(xié)議模型的角度來理解HTTP請求和響應如何傳遞的。 2,、TCP/IP概述 我們以RFC 1180中的圖作為參考 上圖展示了四層TCP/IP協(xié)議圖,,其中network applications是應用程序,,屬于應用層;TCP和UDP主要是傳輸數(shù)據(jù),,屬于傳輸層,,TCP確保端對端的可靠傳輸并盡量確保網(wǎng)絡健康運行,而UDP是簡單不可靠傳輸,;IP主要解決路由問題,,屬于網(wǎng)絡層;ARP是網(wǎng)絡地址轉換,,主要用來轉換IP地址和MAC地址,,介于數(shù)據(jù)鏈路層和網(wǎng)絡層之間,可以看成2.5層,;ENET在這里是數(shù)據(jù)鏈路層,,網(wǎng)卡驅動屬于這一層,主要做具體的介質傳輸,,前面示例中的廣告請求抓包就是在數(shù)據(jù)鏈路層抓取,。 值得注意的是,ARP在linux系統(tǒng)里屬于網(wǎng)絡層,,而在RFC里是介于數(shù)據(jù)鏈路層和網(wǎng)絡層之間,。在《TCP/IP詳解》一書里,ARP被放到了數(shù)據(jù)鏈路層,。當解決實際問題的時候,,我們應該把ARP放到網(wǎng)絡層。 上圖給出使用TCPCopy在不同層發(fā)包的使用方法,。如果TCPCopy從數(shù)據(jù)鏈路層發(fā)包,,由于沒有享受到ARP服務,用戶需要在使用TCPCopy的時候額外加上MAC地址,;而如果TCPCopy從IP層發(fā)包,,則無需指定MAC地址。 本課程主要講述TCP相關案例,,沒有特殊說明的話,,TCP特指傳輸層的TCP,。 3,、什么是TCP TCP即傳輸控制協(xié)議,是一種面向連接的,、可靠的,、基于字節(jié)流的通信協(xié)議。TCP的主要工作是定義端口標識應用程序的身份,,實現(xiàn)端對端的可靠通信,,并進行擁塞控制,,防止互聯(lián)網(wǎng)崩塌。 TCP有如下關鍵特性: 由于TCP是面向連接的協(xié)議,,所以是一種有狀態(tài)的協(xié)議,,而有狀態(tài)的協(xié)議往往比較復雜,因此TCP學習起來也比較困難,。 通過狀態(tài)圖來查看一下TCP狀態(tài)的復雜性: 上圖展示了錯綜復雜的TCP狀態(tài)圖,,然而現(xiàn)實更加復雜。 現(xiàn)實中的TCP狀態(tài)圖其實是這樣的: 圖中,,不僅SYN_RCVD狀態(tài)能夠收到reset數(shù)據(jù)包(圖中RST,,reset數(shù)據(jù)包是重置連接的數(shù)據(jù)包,可以使TCP狀態(tài)瞬間變?yōu)镃LOSED狀態(tài),,而CLOSED狀態(tài)是無法追蹤的),,而且FIN_WAIT1、FIN_WAIT2,、ESTABLISHED,、SYN_SENT和CLOSE_WAIT都能被reset數(shù)據(jù)包打回到CLOSED狀態(tài)。不僅如此,,TCP狀態(tài)還受到超時的影響,。例如Linux系統(tǒng),一旦連接處于FIN_WAIT_2,,在60秒內(默認)如果沒有接收到對端的FIN數(shù)據(jù)包,,系統(tǒng)會把此連接狀態(tài)FIN_WAIT_2直接變到CLOSED狀態(tài)。雖然Linux這樣做是為了防止攻擊,,但這種超時就干掉連接狀態(tài)的做法,,很可能誤殺了很多正常連接,從而使問題更加捉摸不定,。 在互聯(lián)網(wǎng)領域,,很多詭異的問題跟TCP狀態(tài)有關系,課程后續(xù)會有較多案例來講述這些靈異問題,。 4,、端口 當我們去連接服務器程序時,需要指明服務器端口,。為什么需要端口呢,?因為系統(tǒng)是通過端口來區(qū)分不同應用程序,TCP通過端口找到上層應用,。 需要注意的是,,端口號是有限的,端口號最大為65535,,能夠利用的端口數(shù)量隨配置而定,。例如在壓力測試過程中,,一臺機器可以利用的TCP端口是有限的,能夠利用的連接(客戶端端口,,客戶端IP,,服務器應用端口,服務器IP地址)是有限的,。為了解決這個問題,,可以配置多IP地址來擴大可用連接數(shù)量。系統(tǒng)支持同一個端口,,不同的IP地址來綁定不同的應用,。Linux高版本系統(tǒng)下,在綁定同一個IP地址的情況下,,我們還可以利用REUSEPORT機制使不同應用程序共享同一個監(jiān)聽端口,,這對高性能服務器開發(fā)是非常有用的。我們開發(fā)的數(shù)據(jù)庫中間件cetus就利用這個機制來解決短鏈接風暴的問題,。 5,、IP 網(wǎng)絡層的主要工作是定義網(wǎng)絡地址,,區(qū)分網(wǎng)段,,子網(wǎng)內MAC尋址,對不同子網(wǎng)的數(shù)據(jù)包進行路由,。IP的主要作用就是在復雜的網(wǎng)絡環(huán)境中將數(shù)據(jù)包發(fā)給最終的目標地址,。 IP是面向無連接的,,是無狀態(tài)的協(xié)議。IP為什么被設計成無狀態(tài)呢,? 1. 無狀態(tài)協(xié)議處理簡單 2. 通信之前無需建立連接 3. TCP已經面向連接服務了,,IP層可以委托TCP來解決面向連接的問題 4. 由于不帶有狀態(tài),互聯(lián)網(wǎng)路由起來更加自由,,容錯性也更強 值得注意的是,,現(xiàn)實中的IP層往往都帶有安全過濾,甚至有些路由器,,防火墻等中途設備還會干涉應用(例如通過reset數(shù)據(jù)包來干涉TCP會話),,為了更好的做安全檢測,IP層還增加了connection tracking,,在無狀態(tài)協(xié)議上面來追蹤上層連接,。這種方式提高了安全性,但有時也會帶來新的問題,,我們后面有案例具體講述connnection tracking帶來的坑的故事,。 6,、TCP Socket 應用程序通過TCP socket接口來調用TCP服務,,從而達到傳遞數(shù)據(jù)的目的,。每一個TCP socket會被綁定到一個端口,TCP socket雙向都可以通信,,在發(fā)送數(shù)據(jù)的同時,,還可以接收數(shù)據(jù)。 值得注意的是,,應用程序發(fā)送完數(shù)據(jù),,只代表通過TCP socket委托給TCP的工作已經完成,不代表發(fā)送給對端完畢,,應用發(fā)送數(shù)據(jù)和TCP傳輸數(shù)據(jù)不是同步的,。 7、How TCP/IP Works 當用戶通過TCP socket接口發(fā)送請求后,,TCP協(xié)議模塊接管了請求傳遞,,TCP先把請求拆分成一個個更小的數(shù)據(jù)分段(假設TCP offload沒有開啟的情況下),通過IP層發(fā)送出去,。在IP層,,這些數(shù)據(jù)分段會被封裝成IP數(shù)據(jù)包,通過數(shù)據(jù)鏈路層發(fā)送給互聯(lián)網(wǎng)(見下圖),。這些數(shù)據(jù)包經過互聯(lián)網(wǎng)的多個路由器到達目的地,。由于IP網(wǎng)絡是無狀態(tài)的協(xié)議,每一個數(shù)據(jù)包走的路徑可能不一樣,,而且到達的順序也有可能不一樣,,這就要求對端的TCP需要重新組裝數(shù)據(jù)包,以確保向應用層傳遞的數(shù)據(jù)是用戶能夠識別的用戶請求,,這樣服務器應用程序就可以處理用戶發(fā)起的請求了,。 下圖中,假設用戶請求拆分成兩個IP數(shù)據(jù)包 第一個IP數(shù)據(jù)包可能經過A,,B,,C,G,,如下圖,。 第二個數(shù)據(jù)包可能經過A,B,,E,,G(在B點選擇了E節(jié)點,導致路徑不同),,如下圖,。 導致數(shù)據(jù)包在B節(jié)點走向不同路徑的原因可能有很多種,例如C節(jié)點暫時不如E節(jié)點通暢或者臨時發(fā)生了網(wǎng)絡擁塞,這與在高速道路駕駛的原理差不多,。 由于網(wǎng)絡環(huán)境多變,,還可能第二個數(shù)據(jù)包先到達服務器,這時TCP會負責處理out of order的情況,;如果網(wǎng)絡傳遞過程中,,某一個路由器由于過于繁忙,把第一個數(shù)據(jù)包丟了,,那么客戶端的TCP會負責重傳第一個數(shù)據(jù)包,,確保服務器端的TCP能夠不會因為丟包而收不到第一個數(shù)據(jù)包。 如果用戶請求內容很大,,如上傳一個大文件,,就會被拆分成大量數(shù)據(jù)分段,而TCP傳輸這些數(shù)據(jù)分段的時候,,往往還會考慮整個互聯(lián)網(wǎng)能夠接收的程度和對方能夠接收的程度,,發(fā)送數(shù)據(jù)過于貪婪不僅會連累整個互聯(lián)網(wǎng),對方也未必能夠接收得了,,而且還可能使自己速度更慢,,這有點像道路駕駛一樣,不能過于自私,,遵守一定的交通規(guī)則才能使道路通暢,。在互聯(lián)網(wǎng)傳輸數(shù)據(jù)方面,這些交通規(guī)則算法就是赫赫有名的網(wǎng)絡擁塞控制算法,,而對方能否接收得了,,則通過發(fā)送窗口的方式進行控制??傮w來說,,一次發(fā)送數(shù)據(jù)的大小是根據(jù)對方的接收窗口大小和擁塞控制算法來綜合決定的。 從上面可以看出,,IP負責在互聯(lián)網(wǎng)傳輸數(shù)據(jù),,而TCP負責數(shù)據(jù)傳輸可靠并且盡量使網(wǎng)絡健康運行,兩者合作完成了請求的傳遞,,這也是互聯(lián)網(wǎng)應用工作的普遍方式,。 需要注意的是,TCP負責跟TCP進行交互,,應用層無需去實現(xiàn)TCP的功能,,只需要委托給TCP來完成數(shù)據(jù)傳輸,這種隔離的方式給應用層的開發(fā)/運維/測試帶來了方便,,另外,,當出現(xiàn)TCP相關問題時,,解決問題的難度也大大增加。 8,、TCP經驗知識 在多年實戰(zhàn)過程中,,我們發(fā)現(xiàn)以下TCP經驗對工作很有幫助??偨Y如下: 1. 距離越遠,,延遲越大,,重傳概率越大 2. 網(wǎng)絡狀況好壞,,直接影響應用程序性能 3. 不同環(huán)境,采用不同的擁塞算法 4. 擁塞控制算法是互聯(lián)網(wǎng)的精華,,是互聯(lián)網(wǎng)大獲成功的關鍵因素之一 5. TCP是有狀態(tài)協(xié)議,,采用異步處理 6. 抓包分析是找到TCP相關問題根本原因的利器 7. TCP客戶端和TCP服務器端之間的交互,是應用層所有應用公共的交互部分,,理解了這部分原理,,可以解決大量TCP相關問題。 9,、IP經驗知識 在IP經驗知識方面,,我們大致總結如下: 1. 數(shù)據(jù)包選擇路徑不是固定的,到達的順序也可能是亂序的 2. 安全過濾,,坑多的地方 3. 無狀態(tài)協(xié)議,,簡化互聯(lián)網(wǎng)架構,是互聯(lián)網(wǎng)大獲成功的關鍵因素之一 4. IP層對TCP傳遞過來的數(shù)據(jù)包很少分片處理 5. 中途設備不僅僅具備路由功能,,而且還會干涉TCP會話(靈異問題的溫床) 10,、結束語 TCP/IP網(wǎng)絡是互聯(lián)網(wǎng)的基石,了解TCP/IP是如何工作的,,對于我們解決問題是非常有幫助的,。 |
|