Linux虛擬服務器是實現高可伸縮、高可用網絡服務的Linux集群。我們在Linux內核中實現了三種基於IP層負載平衡調度的方法,能靈活高效地將一組服務器組成一個高可伸縮的、高可用的網絡服務。通過在服務器集群中透明地加入和刪除結點實現系統的伸縮性,通過檢測結點或服務進程故障和正確地重置系統達到高可用性。本文詳細討論了Linux虛擬服務器的體系結構及設計方法。
隨著Internet的飛速發展和對我們生活的深入影響,越來越多的個人在互聯網上購物、娛樂、休閒、與人溝通、獲取信息;越來越多的企業把他們與顧客和業務伙伴之間的聯絡搬到互聯網上,通過網絡來完成交易,建立與客戶之間的聯系。互聯網的用戶數和網絡流量正以幾何級數增長,這對網絡服務的可伸縮性提出很高的要求。如熱門的Web站點會因為被訪問次數急劇增長和不能及時處理用戶的請求,而導致用戶長時間的等待。另外,隨著電子商務等關鍵性應用在網上運行,任何例外的服務中斷都將造成不可估量的損失,服務的高可用性也越來越重要。
與之相應地,對用硬件和軟件方法實現高可伸縮、高可用網絡服務的需求也在不斷增長。單服務器顯然不能處理不斷增長的負載。這種服務器升級方法有下列不足:一是升級過程煩瑣,機器切換會使服務暫時中斷,並造成原有計算資源的浪費;二是越往高端的服務器,所花費的代價越大;三是一旦該服務器或應用軟件失效,會導致整個服務的中斷。通過高性能網絡或局域網互聯的服務器集群正成為實現高可伸縮的、高可用網絡服務的有效結構。這種松耦合結構比單處理系統和緊耦合的多處理器系統具有更好的伸縮性和性能價格比,但是,這裡有很多挑戰性的工作,如何在集群系統實現並行網絡服務,它對外是透明的,它具有良好的可伸縮性和可用性。
針對以上需求,我們給出了三種基於IP層負載平衡調度的解決方法,並在Linux內核中實現了這三種方法,將一組服務器構成一個實現可伸縮的、高可用網絡服務的服務器集群,我們稱之為Linux虛擬服務器(Linux Virtual Server)。在LVS集群中,使得服務器集群的結構對客戶是透明的,客戶訪問集群提供的網絡服務就像訪問一台高性能、高可用的服務器一樣。客戶程序不受服務器集群的影響,不需作任何修改。系統的伸縮性通過在服務機群中透明地加入和刪除一個節點來達到,通過檢測節點或服務進程故障和正確地重置系統達到高可用性。
相關的解決方法
在網絡服務中,一端是客戶程序,另一端是服務程序,在中間可能有代理程序。由此看來,可以在不同的層次上實現多台服務器的負載均衡。用集群解決網絡服務性能問題的現有方法主要分為以下四類:
● 基於客戶端的方法
在Berkeley的Smart Client中,客戶端的Applet向一組服務器查詢負載情況,選出負載輕的服務器,再向該服務器發服務請求;當服務器失效時, Applet會嘗試其他服務器。
● 服務端的RR-DNS方法
NCSA的可伸縮的Web服務器系統就是最早基於輪轉域名系統RR-DNS(Round-Robin Domain Name System)的原型系統。其基本思想是:通過RR- DNS服務器把域名輪流解析到這組Web服務器的不同IP地址,將負載分到各台服務器上,從而提高整個系統的性能。然而,該方法存在以下問題:第一,域名服務系統是按層次結構組織的,各級域名服務器都會緩沖已解析的名字到IP地址的映射,它會妨礙Round- Robin方法在客戶端生效,從而導致不同WEB服務器間嚴重的負載不平衡,另外,域名到IP地址映射的TTL(Time To Live)值較難設定。第二,由於用戶訪問請求的突發性和訪問方式不同,即使TTL值為0,各服務器間的負載仍存在較嚴重的負載不平衡。第三,系統的可靠性和可維護性差,一台服務器失效或管理員對其進行維護,均會導致域名已被解析到該服務器的用戶出現服務中止。
● 服務端的應用層負載平衡調度方法
EDDIE、Reverse-Proxy和SWEB都使用基於應用層調度的方法來建立一個可伸縮的WEB服務器。它們都將到達的HTTP請求轉發到不同的Web 服務器,取得結果後,再返回給用戶。該方法也存在一些問題:首先,從請求到達至處理結束,調度器需要進行四次從核心與用戶空間的切換,從用戶到調度器和調度器到真實服務器的兩次TCP連接,系統處理開銷特別大,致使系統的伸縮性有限。其次,基於應用層的負載平衡調度器與應用協議密切相關,對於HTTP、Proxy和SMTP等應用協議,需要寫不同的調度器。
● 服務端的IP層負載平衡調度方法
Berkeley的MagicRouter、Cisco的LocalDirector、Altheon 的ACEDirector和F5的Big/IP等都是使用網絡地址轉換方法。MagicRouter是在Linux 1.3 版本上應用快速報文插入技術,使得進行負載平衡調度的用戶進程訪問網絡設備接近核心空間的速度,降低了上下文切換的處理開銷,但並不徹底,它只是研究的原型系統,沒有成為有用的系統存活下來。
LVS集群的體系結構
LVS采用基於IP層負載平衡調度技術,在操作系統核心空間中將IP層上的TCP/UDP請求均衡地轉移到不同的服務器上,且調度器自動屏蔽掉服務器的故障,從而將一組服務器構成一個高性能的、高可用的虛擬服務器。為此,在設計時需要考慮系統的透明性、可伸縮性、高可用性和易管理性。LVS集群的體系結構如圖1所示,它有3個主要組成部分:
● 負載調度器(Load Balancer),它是整個集群對外面的前端機,負責將客戶的發送到一組服務器上執行,而客戶認為服務是來自一個IP地址上的。
● 服務器池(Server Pool),是一組真正執行客戶請求的服務器,執行的服務有WEB、MAIL、FTP和DNS等。
● 後端存儲(Backend Storage),它為服務器池提供一個共享的存儲區,這樣很容易使得服務器池擁護相同的內容提供相同的服務。
調度器采用基於IP層負載平衡調度技術。當客戶請求到達時,調度器根據負載情況從服務器池中選出一個服務器,將該請求轉發到選出的服務器,並記錄這個調度。所有的操作都是在操作系統核心空間中完成的,它的調度開銷很小,所以它能調度很多服務器,而本身不會成為系統的瓶頸。服務器池的結點數目是可變的。當整個系統收到的負載超過目前所有結點的處理能力時,可以在服務器池中增加服務器來滿足不斷增長的請求負載。對大多數網絡服務來說,結點與結點間不存在很強的相關性,所以整個系統的性能可以隨著服務器池的結點數目增加而線性增長。
集群系統的特點是它在軟硬件上都有冗余。系統的高可用性可以通過檢測節點或服務進程故障和正確地重置系統來實現。通常,在調度器上由資源監視進程來時刻監視各個服務器結點的健康狀況,當服務器對ICMP ping不可達或網絡服務在指定的時間沒有響應時,資源監視進程通知操作系統內核,將該服務器從調度列表中刪除或者失效。這樣,新的服務請求就不會被調度到壞的結點。
現在前端的調度器有可能成為系統的單一失效點。為了避免調度器失效導致整個系統不能工作,需要設立調度器的備份。兩個心跳進程(Heartbeat Daemon)分別在主、從調度器上運行,它們通過串口線和UDP等心跳線來相互匯報各自的健康情況。當從調度器不能聽到主調度器的心跳時,從調度器會接管主調度器的工作提供負載調度服務。一般通過ARP欺騙(Gratuitous ARP)來接管集群的Virtual IP Address。當主調度器恢復時,將自動變成從調度器,或從調度器釋放Virtual IP Address,主調度器收回Virtual IP Address並提供負載調度服務。然而,主調度器接管後會導致已有的調度信息丟失,需要客戶程序重新發送請求。
後端存儲通常用容錯的分布式文件系統,如AFS、GFS、 Coda和Intermezzo等。這些系統會考慮文件訪問的伸縮性和可用性。各服務器訪問分布式文件系統就像訪問本地文件系統一樣。然而,當不同服務器上的應用程序同時訪問分布式文件系統上同一資源時,應用程序的訪問沖突需要消解才能使得資源處於一致狀態。這需要一個分布式鎖管理器(Distributed Lock Manager),它可能是分布式文件系統內部提供的,也可能是外部的。
IP負載均衡技術
LVS實現了三種IP負載均衡技術,它們分別為VS/NAT、 VS/TUN和VS/DR。以下幾小節將描述它們的工作原理和它們的優缺點。在以下描述中,我們稱客戶的socket和服務器的socket之間的數據通信為連接,無論它們是使用TCP還是UDP協議。
Virtual Server via Network Address Translation(VS/NAT)
由於IPv4中IP地址空間的日益緊張和安全方面的原因,很多網絡使用Internet上未被分配的保留IP地址(10.0.0.0/255.0.0.0、172.16.0.0/255.128.0.0 和192.168.0.0/255.255.0.0)。當內部網絡中的主機要訪問Internet或被Internet訪問時,就需要采用網絡地址轉換(Network Address Translation, 以下簡稱NAT),將內部地址轉化為 Internet上可用的外部地址。NAT的工作原理是報文頭(目標地址、源地址和端口等)被正確改寫後,客戶相信它們連接一個IP地址,而不同IP地址的服務器組也認為它們是與客戶直接相連的。由此,可以用NAT方法將不同IP地址的並行網絡服務變成在一個IP 地址上的一個虛擬服務。
VS/NAT的體系結構如圖2所示。在一組服務器前有一個調度器,用戶通過Virtual IP Address(即調度器的外部地址)訪問服務時,請求報文到達調度器,調度器以負載均衡方法從一組真實服務器選出一個,將報文的目標地址Virtual IP Address改寫成選定服務器的地址,報文的目標端口改寫成選定服務器的相應端口,最後將報文發送給選定的服務器。同時,調度器在Hash表中記錄這個連接,當這個連接的下一個報文到達時,從Hash表中可以得到原選定服務器的地址和端口,進行同樣的改寫操作,並將報文傳給原選定的服務器。真實服務器的回應報文經過調度器時,將報文的源地址和源端口改為Virtual IP Address和相應的端口,再把報文發給用戶。當連接終止或超時,調度器將這個連接從Hash表中刪除。這樣,用戶所看到的只是在Virtual IP Address 上提供的服務,而虛擬服務器的結構對用戶是透明的。對改寫後的報文,應用增量調整 Checksum的算法調整TCP Checksum的值,避免了掃描整個報文來計算Checksum的開銷。 Virtual Server via IP Tunneling (VS/TUN)
在VS/NAT的集群系統中,請求和應答的數據包都需要通過負載調度器,當實際服務器的數量超過20時,負載調度器將成為集群系統的新瓶頸。許多Internet服務都有這樣的特點:請求報文較短而響應報文往往包含大量的數據。如果能將請求和響應分開處理,即在負載調度器中只負責調度請求而響應直接返回給客戶,將極大地提高整個集群系統的吞吐量。
利用IP隧道技術將請求報文封裝轉發給後端服務器,響應報文能從後端服務器直接返回給客戶。但在這裡,後端服務器有一組而非一個,所以我們不可能靜態地建立一一對應的隧道,而是動態地選擇一台服務器,將請求報文封裝和轉發給選出的服務器。這樣,我們可以利用IP隧道的原理將一組服務器上的網絡服務組成在一個IP地址上的虛擬網絡服務。VS/TUN的體系結構如圖3所示,各個服務器將 VIP地址配置在自己的IP隧道設備上
VS/TUN的連接調度和管理與VS/NAT中的一樣,只是它的報文轉發方法不同。調度器根據各個服務器的負載情況,動態地選擇一台服務器,將請求報文封裝在另一個IP報文中,再將封裝後的IP報文轉發給選出的服務器;那台服務器收到報文後,先將報文解封獲得原來目標地址為VIP的報文,服務器發現VIP地址被配置在本地的IP隧道設備上,所以就處理這個請求,然後根據路由表將響應報文直接返回給客戶。
Virtual Server via Direct Routing(VS/DR)
這種IP層負載均衡方法與IBM的NetDispatcher中的方法類似。它的體系結構如圖4所示:調度器和服務器組都必須在物理上有一個網卡通過不分斷的局域網相連,如通過交換機或者高速的HUB相連。VIP地址為調度器和服務器組共享,調度器配置的VIP地址是對外可見的,用於接收虛擬服務的請求報文;所有的服務器把VIP地址配置在各自的Non-ARP網絡設備上,它對外面是不可見的,只是用於處理目標地址為VIP的網絡請求。
VS/DR的連接調度和管理與VS/NAT和VS/TUN中的一樣,它的報文轉發方法又有不同,將報文直接路由給目標服務器。在VS/DR中,調度器根據各個服務器的負載情況,動態地選擇一台服務器,不修改也不封裝IP報文,而是將數據幀的MAC地址改為選出服務器的MAC地址,再將修改後的數據幀在與服務器組的局域網上發送;因為數據幀的MAC地址是選出的服務器,所以服務器肯定可以收到該報文,發現VIP地址被配置在本地的網絡設備上,所以就處理這個請求,然後根據路由表將響應報文直接返回給客戶。
三種方法的優缺點
三種IP負載均衡技術的優缺點歸納在下表中:
● Virtual Server via NAT
VS/NAT的優點是服務器可以運行任何支持TCP/IP的操作系統,它只需要一個IP地址配置在調度器上,服務器組可以用私有的IP地址。缺點是它的伸縮能力有限,當服務器結點數目升到20時,調度器本身有可能成為系統的新瓶頸,因為在VS/NAT中請求和響應報文都需要通過負載調度器。在Pentium 166主機上測得重寫報文的平均延時為60us,假設TCP報文的平均長度為536 Bytes,則調度器的最大吞吐量為8.93 MBytes/s。再假設每台服務器的吞吐量為600KBytes/s,這樣一個調度器可以帶動16台服務器。
● Virtual Server via IP Tunneling
在VS/TUN的集群系統中,負載調度器只將請求調度到不同的實際服務器,實際服務器將應答的數據直接返回給用戶。這樣,負載調度器就可以處理巨量的請求,而不會成為系統的瓶頸。即使負載調度器只有100Mbps的全雙工網卡,虛擬服務器的最大吞吐量可以達到幾Gbps。所以,VS/TUN可以極大地增加負載調度器調度的服務器數量,它可以用來構建高性能超級服務器。VS/TUN技術對服務器的要求是所有的服務器必須支持“IP Tunneling”或者“IP Encapsulation”協議。目前,VS/TUN 的後端服務器主要運行Linux操作系統。因為“IP Tunneling”正成為各個操作系統的標准協議,所以VS/TUN也會適用運行其他操作系統的後端服務器。
● Virtual Server via Direct Routing
同VS/TUN一樣,VS/DR調度器只處理客戶到服務器端的連接,響應數據可以直接從獨立的網絡路由返回給客戶。這可以極大地提高LVS集群系統的伸縮性。同VS/TUN相比,這種方法沒有IP隧道的開銷,但是要求負載調度器與實際服務器都有一塊網卡連在同一物理網段上,服務器網絡設備或者設備別名不作ARP 響應。
連接調度
負載平衡調度是以連接為粒度的。在HTTP協議(非持久)中,每個對象從WEB服務器上獲取都需要建立一個TCP連接,同一用戶的不同請求會被調度到不同的服務器上,所以這種細粒度的調度完全避免了用戶訪問的突發性引起的負載不平衡。我們已實現了以下4種調度算法:
輪轉調度(Round-Robin Scheduling)
加權輪轉調度(Weighted Round-Robin Scheduling)
最小連接調度(Least-Connection Scheduling)
加權最小連接調度(Weighted Least-Connection Scheduling)
輪轉調度算法是假設所有服務器處理性能均相同,依次將請求調度不同的服務器,算法簡單,但不適用於服務器組中處理性能不一的情況。為此使用加權輪轉調度算法,用相應的權值表示服務器的處理性能,將請求數目按權值的比例分配到各服務器。權值高的服務器先收到連接,權值高的服務器比權值低的服務器處理更多的連接,相同權值的服務器處理相同數目的連接數。
最小連接調度是需要記錄各個服務器已建立TCP連接的數目,把新的連接請求發送當前連接數最小的服務器。當各個服務器有相同的處理性能時,最小連接調度能把負載變化大的請求平滑分布到各個服務器上,所有處理時間比較長的請求不可能被發送到同一台服務器上。但是,當各個服務器的處理能力不同時,該算法並不理想,因為TCP連接處理請求後會進入TIME_WAIT狀態,TCP的TIME_WAIT 一般為2分鐘,此時連接還占用服務器的資源,所以會出現這樣情形,性能高的服務器已處理所收到的連接,連接處於TIME_WAIT狀態,而性能低的服務器既要忙於處理所收到的連接,還要收到新的連接請求。加權最小連接調度是最小連接調度的超集,各個服務器用相應的權值表示其處理性能。假設每台服務器的權值為Wi(i=1..n),TCP連接數目為 Ti(i=1..n),依次選Ti/Wi為最小者的服務器為調度對象。
Linux虛擬服務器在Linux內核實現了三種IP負載調度技術和四種連接調度算法。通過負載平衡調度、故障檢測技術和集群管理等,將一組服務器組成一個高性能、高可用的網絡服務。該系統具有良好的伸縮性,支持幾百萬個並發連接。無需對客戶機和服務器作任何修改,可適用任何Internet站點。