1. 程式人生 > >Web基礎架構:負載均衡和LVS

Web基礎架構:負載均衡和LVS

感謝同事【沐劍】的投稿

在大規模網際網路應用中,負載均衡裝置是必不可少的一個節點,源於網際網路應用的高併發和大流量的衝擊壓力,我們通常會在服務端部署多個無狀態的應用伺服器和若干有狀態的儲存伺服器(資料庫、快取等等)。

一、負載均衡的作用

負載均衡裝置的任務就是作為應用伺服器流量的入口,首先挑選最合適的一臺伺服器,然後將客戶端的請求轉發給這臺伺服器處理,實現客戶端到真實服務端的透明轉發。最近幾年很火的「雲端計算」以及分散式架構,本質上也是將後端伺服器作為計算資源、儲存資源,由某臺管理伺服器封裝成一個服務對外提供,客戶端不需要關心真正提供服務的是哪臺機器,在它看來,就好像它面對的是一臺擁有近乎無限能力的伺服器,而本質上,真正提供服務的,是後端的叢集。

一個典型的網際網路應用的拓撲結構是這樣的:

top

二、負載均衡的型別

負載均衡可以採用硬體裝置,也可以採用軟體負載。

商用硬體負載裝置成本通常較高(一臺幾十萬上百萬很正常),所以在條件允許的情況下我們會採用軟負載,軟負載解決的兩個核心問題是:選誰、轉發,其中最著名的是LVS(Linux Virtual Server)。

三、軟負載——LVS

LVS是四層負載均衡,也就是說建立在OSI模型的第四層——傳輸層之上,傳輸層上有我們熟悉的TCP/UDP,LVS支援TCP/UDP的負載均衡。

LVS的轉發主要通過修改IP地址(NAT模式,分為源地址修改SNAT和目標地址修改DNAT)、修改目標MAC(DR模式)來實現。

那麼為什麼LVS是在第四層做負載均衡?

首先LVS不像HAProxy等七層軟負載面向的是HTTP包,所以七層負載可以做的URL解析等工作,LVS無法完成。其次,某次使用者訪問是與服務端建立連線後交換資料包實現的,如果在第三層網路層做負載均衡,那麼將失去「連線」的語義。軟負載面向的物件應該是一個已經建立連線的使用者,而不是一個孤零零的IP包。後面會看到,實際上LVS的機器代替真實的伺服器與使用者通過TCP三次握手建立了連線,所以LVS是需要關心「連線」級別的狀態的。

LVS的工作模式主要有4種:

DR

NAT

TUNNEL

Full-NAT

這裡挑選常用的DR、NAT、Full-NAT來簡單介紹一下。

1、DR

dr

請求由LVS接受,由真實提供服務的伺服器(RealServer, RS)直接返回給使用者,返回的時候不經過LVS。

DR模式下需要LVS和繫結同一個VIP(RS通過將VIP繫結在loopback實現)。

一個請求過來時,LVS只需要將網路幀的MAC地址修改為某一臺RS的MAC,該包就會被轉發到相應的RS處理,注意此時的源IP和目標IP都沒變,LVS只是做了一下移花接木。

RS收到LVS轉發來的包,鏈路層發現MAC是自己的,到上面的網路層,發現IP也是自己的,於是這個包被合法地接受,RS感知不到前面有LVS的存在。

而當RS返回響應時,只要直接向源IP(即使用者的IP)返回即可,不再經過LVS。

DR模式是效能最好的一種模式。

2、NAT

nat

NAT(Network Address Translation)是一種外網和內網地址對映的技術。

NAT模式下,網路報的進出都要經過LVS的處理。LVS需要作為RS的閘道器。

當包到達LVS時,LVS做目標地址轉換(DNAT),將目標IP改為RS的IP。RS接收到包以後,彷彿是客戶端直接發給它的一樣。

RS處理完,返回響應時,源IP是RS IP,目標IP是客戶端的IP。

這時RS的包通過閘道器(LVS)中轉,LVS會做源地址轉換(SNAT),將包的源地址改為VIP,這樣,這個包對客戶端看起來就彷彿是LVS直接返回給它的。客戶端無法感知到後端RS的存在。

3、Full-NAT

無論是DR還是NAT模式,不可避免的都有一個問題:LVS和RS必須在同一個VLAN下,否則LVS無法作為RS的閘道器。

這引發的兩個問題是:

1、同一個VLAN的限制導致運維不方便,跨VLAN的RS無法接入。

2、LVS的水平擴充套件受到制約。當RS水平擴容時,總有一天其上的單點LVS會成為瓶頸。

Full-NAT由此而生,解決的是LVS和RS跨VLAN的問題,而跨VLAN問題解決後,LVS和RS不再存在VLAN上的從屬關係,可以做到多個LVS對應多個RS,解決水平擴容的問題。

Full-NAT相比NAT的主要改進是,在SNAT/DNAT的基礎上,加上另一種轉換,轉換過程如下:

fullnat

在包從LVS轉到RS的過程中,源地址從客戶端IP被替換成了LVS的內網IP。

內網IP之間可以通過多個交換機跨VLAN通訊。

當RS處理完接受到的包,返回時,會將這個包返回給LVS的內網IP,這一步也不受限於VLAN。

LVS收到包後,在NAT模式修改源地址的基礎上,再把RS發來的包中的目標地址從LVS內網IP改為客戶端的IP。

Full-NAT主要的思想是把閘道器和其下機器的通訊,改為了普通的網路通訊,從而解決了跨VLAN的問題。採用這種方式,LVS和RS的部署在VLAN上將不再有任何限制,大大提高了運維部署的便利性。

4、Session

客戶端與服務端的通訊,一次請求可能包含多個TCP包,LVS必須保證同一連線的TCP包,必須被轉發到同一臺RS,否則就亂套了。為了確保這一點,LVS內部維護著一個Session的Hash表,通過客戶端的某些資訊可以找到應該轉發到哪一臺RS上。

5、LVS叢集化

採用Full-NAT模式後,可以搭建LVS的叢集,拓撲結構如下圖:

cluster

6、容災

容災分為RS的容災和LVS的容災。

RS的容災可以通過LVS定期健康檢測實現,如果某臺RS失去心跳,則認為其已經下線,不會在轉發到該RS上。

LVS的容災可以通過主備+心跳的方式實現。主LVS失去心跳後,備LVS可以作為熱備立即替換。

容災主要是靠KeepAlived來做的。


王 晨純

資深Java研發工程師,關注系統穩定性、效能優化、Web系統架構。