TCP粘合技術原理

 原文地址:http://www.ibm.com/developerworks/cn/linux/cluster/cluster_system/balance/part6/index.html

集羣的可擴展性及其分佈式體系結構之十

TCP粘合技術原理

林凡,現於廈門大學從事Linux相關的科研工作。於集羣技術由很大的興趣,希望能與志同道合的朋友一起交流。您可以通過電子郵件[email protected]和他聯繫。

簡介: 本部分,將對面向內容交換的負載平衡中,使用的主要網絡通信技術手段進行分析。其中,關於通信的半工(TCP HandOff)和雙工(TCP Splicing粘合模式)是目前Content Switch(面向內容交換)集羣系統使用的主要技術。傳統的負載平衡技術主要有應用層協議代理服務器、三層和四層交換等。其中,應用層代理技術,面向特定的應用層協議,對客戶端和服務器的數據流進行轉換;三層和四層交換通過識別數據報文的有效地址信息進行雙向的映射和調度。不管採用哪一種技術,其根本模式都是在網絡連接的基礎上進一步對數據包進行業務級分流。

<!--

-->

發佈日期: 2003 年 6 月 09 日
級別: 初級
訪問情況 : 2648 次瀏覽
評論: 0 (查看 | 添加評論 - 登錄)

平均分 2 星 共 3 個評分 平均分 (3個評分)
爲本文評分

1、應用級代理

應用級代理廣泛的應用於HTTP代理,HTTP緩存等領域,扮演着當今重要的網絡服務角色。

一般的應用層代理都採用應用層連接粘合代理(split-connection),代理服務器位於客戶端和被訪問的服務站點之間,代理服務器透明的將客戶請求和服務器響應進行雙向轉換,以協助雙方完成通信的全過程。從HTTP緩存服務器(衆所周知的Squid)到安全防火牆,代理服務器始終保持了對現有網絡服務協議的兼容性(主要是HTTP等)以及對現有應用框架的集成性。

當用戶提交請求,代理將請求轉發給服務器,對於服務器而言,代理充當了客戶端的角色;當服務器響應請求,代理收到後將數據返回客戶端,對於客戶端而言,充當服務端的角色。

但是,連接粘合代理存在着幾大致命的問題:首先,代理服務器的性能始終是大規模通信的瓶頸;其次,由於代理服務器對任何方向上的數據都要進行轉換,大大增加了通信延遲;最後,代理本質上對端到端的傳輸協議進行了修改,難免會存在傳輸協議的兼容性問題。

因此,在集羣應用中,特別是大規模負載平衡集羣系統中很難看到應用級代理的身影。


圖一:應用層代理原理示意圖

當客戶端向服務器發起請求的時候,連接被重定向到代理服務器的指定端口上(例如IE瀏覽器中設定的代理一樣);代理接收到這一連接請求以後,根據請求的目標地址和端口,向被訪問的服務器發出另一個連接請求,並將客戶端發來的請求轉發到目標服務器上;隨後,代理服務器強制在兩個連接上進行互相轉發請求數據和應答數據,成爲客戶端和服務器之間必經之路。因此,代理實現客戶端對服務器的透明訪問。本質上,代理將客戶端的請求進行適當的修改,重新通過另一個連接發送到服務器端,反之依然。這樣子的缺點是顯然的:數據的雙向拷貝需要經由核心的TCP/IP協議棧到用戶空間,修改後再由用戶空間到TCP/IP層進行處理轉發,頻繁的上下文交換導致代理的效率低下。而代理服務器也不得不維護至少雙倍於請求數量的連接,這對於代理服務器的內存和CPU調度都有極高的要求。

這類的代理服務器大多數針對特定的應用層協議進行雙向網絡連接的交換工作,比如特定的HTTP、HTTPS代理,FTP代理等,都要求代理服務器理解對應的高層協議的通信原語,因此往往通過一個多線程的用戶進程來實現。


2、核心級的TCP粘合交換技術 ― TCP Splicing

大多數的四層交換產品,都是在網絡傳輸協議層(TCP)進行工作。它們通過轉換數據包的端口和IP地址信息,將數據重新定向到服務節點上。比如,將HTTP請求定向到Web Cache服務器上,或者將請求均勻分配到不同的節點實現負載平衡。而面向內容調度的提出,要求在四層交換的基礎上進一步識別交換數據的內容,以實現智能交換和更高的性能。

傳統的四層交換,在客戶端發出第一個Syn包後,均衡器對服務節點羣進行選擇,並將該SYN後續的報文直接發往選定的節點。處理的模式固然簡單並且有效率,但是對於需要解析報文內容的交換機而言,需要在連接建立後(SYN開始之後並完成三次握手),才從接下來的報文中獲得負載平衡所需的信息(比如,一個HTTP協議的Get的請求,在客戶端完成了連接建立的操作之後,均衡器才能獲得具體的Get指令內容)。這意味着,均衡器不能僅僅根據SYN報文的地址和端口信息就做出調度判斷;而要把調度的決定延遲到相關業務數據到達的時候進行――整體上講,交換被"延遲"了。

於是,原理上,負載均衡器(也就是應用級代理),需要監聽客戶端的連接請求,並在客戶端發出連接的請求之後(從SYN開始),建立客戶端到均衡器之間的連接(通過TCP的三次握手協議完成)。並在隨後的請求報文中分析數據並決定真正被訪問的服務節點,然後才與服務節點建立另一個連接,將兩個連接粘合在一起(Splicing)。


圖二:TCP Splicing原理示意圖

TCP粘合連接的原理如上圖所示。該結構於應用級代理的最大不同在於:客戶端和集羣節點之間的連接在操作系統的核心層進行連接粘合。也就是說,TCP粘合避免了數據包從核心空間到用戶空間的上下文交換這一耗時的過程,並且可以利用操作系統在覈心層TCP/IP協議棧的多線程處理能力,提高TCP連接的交換速度,比如Linux核心2.4。


3、TCP Splicing 處理流程簡要描述

相比於應用層代理而言,TCP Splicing技術避免了數據報文的上下文切換工作,減少了核心空間到用戶進程的通信開銷,整體效率可以作的很好。這一類的技術目前應用的非常穩定有效率,在小型網關設備和簡單的負載平衡集羣系統中,足夠支撐集羣的整體運行。

簡單說,要實現TCP連接的粘合,要經過至少三個步驟:

1、客戶端發起連接請求,並且由均衡器截獲請求,完成和客戶端的三次握手協議,等待客戶端的請求數據(比如Get指令)。


圖三:第一步,客戶端發起連接

2、均衡器接收到客戶端發送的Get請求數據,選定集羣節點後,僞裝成客戶端向集羣節點發起請求,完成三次握手協議。並記錄下兩個連接的本地響應端口,用於映射兩個TCP連接。


圖四:第二步,均衡器向服務節點發起連接

3、經過前面的兩次連接,均衡器在客戶端和被選節點之前建立一個連接的映射關係。而後續兩方的通信就無需再次被分析模塊處理,直接在映射端互相交換就可以了


圖五:第三步,TCP連接粘合完成,數據直接交換


4、TCP Splicing數據包通信流程

這裏我們詳細分析一下TCP粘合處理流程中,對於兩回的三次握手協議之後,再建立起連接映射的具體細節。

從前面的敘述我們知道,負載均衡器在客戶端發起TCP連接請求並完成三次的握手確認後,並沒有馬上將數據轉發,而是先僞裝爲服務節點響應客戶端的請求,並在隨後接收到第一個數據包中獲取負載均衡所需的數據,決定實際的服務節點;並在完成與服務節點的通信確認工作時候纔開始雙方的數據轉換工作。


TCP Splicing數據處理流程

圖中,藍色框線包含起來的部分表示負載均衡器,包括了專門負責監聽客戶端請求的端口和負責發送請求到服務節點的端口。而TCP粘合工作完成之後,實際上客戶端和服務節點雙方的數據包就在兩個端口上直接交換,不需要經過複雜的用戶空間的調度模塊處理了,相當於核心級的報文交換機。

Step1:客戶端向集羣發起請求,典型的請求以一個Syn(CSEQ表示客戶端報文的初始序列)報文爲開始,標記一個TCP連接開始並請求迴應一個三次握手協議過程。該請求到達負載均衡器的客戶端口。

Step2:負載均衡器內建的網絡輸入流處理例程將截獲客戶端的SYN請求報文,解析後轉發給連接管理模塊,並記錄下這一次的請求信息:源地址、源端口號、目標地址和目標端口號。

Step3:負載均衡器迴應一個對應的ACK(CSEQ+1,表示對應於初始序列的應答序列)到客戶端口,回送客戶端監聽口。同時,發起一個Syn(DSEQ表示新的報文序列號)。

Step4:Ack應答數據以及新的Syn報文從客戶端監聽口回送客戶端,客戶端接收響應,第一次握手完成。

衆所周知的是,由於IP網絡是分組轉發的,而接收端試用的緩衝區也會導致收到非完全序列的報文。因此,TCP爲了保證報文發送序列與接收序列的同步,定義了一個報文序列協議規範。關鍵在於:每次發送的報文中所包含的序列,一定是準備接下來接收的ACK應答報文的序列。

Step5:客戶端在收到集羣的正確應答數據後,認爲連接已經建立(實際上,客戶端僅僅是和負載均衡器建立了連接,它被欺騙了J)。向服務端發出數據請求報文DATA(CSEQ+1),並且對均衡器的SYN(DSEQ)進行應答,同時發送ACK(DSEQ+1)。至此完成了三次握手的全部過程,並且開始進行數據通信。

由於面向內容的負載平衡必須在收到客戶端發出的含有協議內容的數據之後(例如Get指令),才能進行負載調度的判斷工作,因此,需要針對客戶端的連接請求進行"欺騙",待於客戶端的連接建立之後將其掛起,準備調度。這樣的操作,顯然延遲了客戶端到實際節點之間的連接進程,也有文獻稱之爲TCP Delay Binding。

Step6:關鍵的一步。真正的請求數據第一次到達了負載均衡器的調度模塊。調度根據請求中的有效協議信息做出負載平衡判斷。判斷的依據可以是請求的文件類型,或者是服務級別。另外,負載平衡器也要根據當前服務節點的權值隊列,選擇目前符合服務條件的負載最輕的節點。而客戶端的請求在這裏將被掛起,從客戶端的角度看,連接請求被隱蔽的延遲了。關於負載平衡策略的討論不是本文的重點,具體的調度算法和平衡策略將在後續篇章中介紹。

Step7:負載均衡器選擇完實際的服務節點,以客戶端的"身份"向服務節點發起SYN連接請求,特別一提的是,該請求使用了客戶端原先發起的請求初始序列號CSEQ。這麼做的目的是爲了後面進行TCP粘合所必須的TCP Header數據轉換時,儘可能減少均衡器的CPU計算量,也方便管理被粘合的兩個連接。

Step8:SYN(CSEQ)由服務端監聽口到達服務節點,從整個會話過程來看,客戶端Step1所發出的SYN(CSEQ)被延遲地發送到了最終目的地!

Step9:服務端接受SYN(CSEQ),送回應答數據包ACK(CSEQ)+1),同時發起SYN(SSEQ)以完成TCP的握手例程。

Step10:值得注意的一個步驟,服務節點的SYN(SSEQ)報文序列被重新映射爲SYN(DSEQ),和step3的報文序列相同。這樣,從負載均衡器的角度來講,他正確的獲得了一個應答報文,並且這個被轉換過序列的應答報文可以直接和客戶端的報文序列映射在一起了。而ACK(CSEQ+1)應答報文被送回核心模塊。

到這裏爲止,我們可以發現,服務端監聽口對於均衡器而言,作爲虛擬的服務端而存在,通過該端口的報文序列都是轉換過後的序列,能夠直接和客戶端監聽口的序列對應。同理,客戶端監聽口也承擔了相似的角色。

Step11:均衡器確認了ACK(CSEQ+1)報文後,完成和服務節點的三次握手。發出應答報文ACK(DSEQ+1)(注意:均衡器在這裏使用的是客戶端序列,把自己當做客戶端,把服務端監聽口當做服務器)。同時發出請求數據Data(CSEQ+1)。

到這一步,均衡器完成了對Step5的TCP請求延遲處理。客戶端的請求數據終於被髮送給了服務節點(通過服務端監聽口)。

Step12:經過服務端監聽口的報文,需要被適當的修改序列:即DSEQ序列->SSEQ序列。這樣的轉換是固定偏移的,也就是第一次SYN被接收之後,二者序列之差可以作爲整個通信過程中,序列轉換的偏移量。因此,從端口送回到服務節點的報文是:Data(CSEQ+1)以及ACK(SSEQ+1)。

Step13:服務節點響應數據請求,例如返回請求的HTML文件。數據DATA(SSEQ+1)以長度len返回,並回送應答ACK(CSEQ+len+1)到均衡器的監聽口。

Step14:監聽口對Data(SSEQ+1)進行轉換,ACK不轉換。並將轉換後的數據,直接傳送到客戶端監聽口,無需經過核心調度模塊的處理。由於前面已經記錄了客戶端的連接信息,因此這樣的傳送非常快速。而客戶端監聽口收到數據之後,即立刻發往客戶端。

Step15:客戶端對剛纔收到的數據應答,將ACK(DSEQ+len+1)送往均衡器。均衡器將該報文發往服務端監聽口。

Step16:服務端監聽口對報文進行映射轉換,DSEQ->SSEQ,向服務節點發送應答報文ACK(SSEQ+len+1)。表明一次數據 請求-回送 工作完成。

TUX是redhat中運行於核心空間的一個簡易Web服務器。

他具備了基本的Web服務器的文件訪問功能和常見的異常處理。對於客戶端請求的如HTML、Gif等靜態頁面文件可以直接處理,無需將數據傳送到用戶空間去處理,通過Linux的核心層API讀文件調用就可以直接返回請求的文件,並且可以利用TCP/IP的多線程能力提高整體吞吐量。但是對於特殊的請求,如CGI等,需要藉助掛接的用戶空間的運行模塊處理,這些模塊可以是支持CGI、PHP的Apache重磅Web服務器,也可以是用戶自己寫的處理模塊。TUX實現了類似TCP粘合模型的處理方式:TUX的通過NetFilter鉤子函數實現了對所有輸入流的處理,並在核心直接完成請求的響應;對於特殊的HTTP請求(分析Get的內容獲得),交給用戶空間的程序處理(好似代理程序)。二者結合滿足性能和功能的兼顧。

均衡器在客戶端和服務節點之間扮演了一個透明網關的角色。二者互相不可見。而爲了順利實現兩個TCP連接數據包的轉換,均衡器設立負責扮演服務的客戶端監聽口和扮演客戶的服務端監聽口。數據包在服務端監聽口進行TCP報文頭的修改工作:序列號的映射,DSEQ<->SSEQ。

並且,均衡器調度核心在適當的時候,根據客戶的請求進行負載平衡調度工作。功能上看,均衡器具備了兩種功能:基於應用層協議解析的負載平衡調度策略,以及基於端口的報文交換。其中,報文交換的對象依賴於負載平衡選擇的服務節點。但報文交換在一次調度策略確定之後就獨立運行(圖中的Step13~Step16),不再經過複雜的處理,可以獲得非常高的性能和擴展性。另外,這麼作也保護了服務節點的安全性。而調度核心獨立於報文交換核心,它僅僅處理需要進行調度的部分報文,例如:包含請求不同文件類型信息的報文,或者是包含Session信息的報文。那麼在設計端口映射管理核心程序的時候,需要對報文進行快速分類,決定哪一類報文可以直接通過報文交換核心,而哪一部分需要交給調度核心處理。

下一部分,我們將對 TCP 粘合技術中一些涉及到TCP/IP協議的具體細節進行研究,以發現該技術中所存在的問題和特性。


參考資料

  • TCP Splicing: A.Cohen , S.Rangatajan, and H.Slye. On the Performance of TCP Splicing for URL-Aware Redirection. In Proceeding of the 2nd USENIX Symposium on Internet Technologies and systems,Boulder CO,Oct,1999

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章