在大規模互聯網應用中,負載均衡設備是必不可少的一個節點,源於互聯網應用的高併發和大流量的衝擊壓力,咱們一般會在服務端部署多個無狀態的應用服務器和若干有狀態的存儲服務器(數據庫、緩存等等)。數據庫
負載均衡設備的任務就是做爲應用服務器流量的入口,首先挑選最合適的一臺服務器,而後將客戶端的請求轉發給這臺服務器處理,實現客戶端到真實服務端 的透明轉發。最近幾年很火的「雲計算」以及分佈式架構,本質上也是將後端服務器做爲計算資源、存儲資源,由某臺管理服務器封裝成一個服務對外提供,客戶端 不須要關心真正提供服務的是哪臺機器,在它看來,就好像它面對的是一臺擁有近乎無限能力的服務器,而本質上,真正提供服務的,是後端的集羣。後端
一個典型的互聯網應用的拓撲結構是這樣的:緩存
負載均衡能夠採用硬件設備,也能夠採用軟件負載。服務器
商用硬件負載設備成本一般較高(一臺幾十萬上百萬很正常),因此在條件容許的狀況下咱們會採用軟負載,軟負載解決的兩個核心問題是:選誰、轉發,其中最著名的是LVS(Linux Virtual Server)。網絡
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來簡單介紹一下。
請求由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模式是性能最好的一種模式。
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的存在。
不管是DR仍是NAT模式,不可避免的都有一個問題:LVS和RS必須在同一個VLAN下,不然LVS沒法做爲RS的網關。
這引起的兩個問題是:
一、同一個VLAN的限制致使運維不方便,跨VLAN的RS沒法接入。
二、LVS的水平擴展受到制約。當RS水平擴容時,總有一天其上的單點LVS會成爲瓶頸。
Full-NAT由此而生,解決的是LVS和RS跨VLAN的問題,而跨VLAN問題解決後,LVS和RS再也不存在VLAN上的從屬關係,能夠作到多個LVS對應多個RS,解決水平擴容的問題。
Full-NAT相比NAT的主要改進是,在SNAT/DNAT的基礎上,加上另外一種轉換,轉換過程以下:
在包從LVS轉到RS的過程當中,源地址從客戶端IP被替換成了LVS的內網IP。
內網IP之間能夠經過多個交換機跨VLAN通訊。
當RS處理完接受到的包,返回時,會將這個包返回給LVS的內網IP,這一步也不受限於VLAN。
LVS收到包後,在NAT模式修改源地址的基礎上,再把RS發來的包中的目標地址從LVS內網IP改成客戶端的IP。
Full-NAT主要的思想是把網關和其下機器的通訊,改成了普通的網絡通訊,從而解決了跨VLAN的問題。採用這種方式,LVS和RS的部署在VLAN上將再也不有任何限制,大大提升了運維部署的便利性。
客戶端與服務端的通訊,一次請求可能包含多個TCP包,LVS必須保證同一鏈接的TCP包,必須被轉發到同一臺RS,不然就亂套了。爲了確保這一點,LVS內部維護着一個Session的Hash表,經過客戶端的某些信息能夠找到應該轉發到哪一臺RS上。
採用Full-NAT模式後,能夠搭建LVS的集羣,拓撲結構以下圖:
容災分爲RS的容災和LVS的容災。
RS的容災能夠經過LVS按期健康檢測實現,若是某臺RS失去心跳,則認爲其已經下線,不會在轉發到該RS上。
LVS的容災能夠經過主備+心跳的方式實現。主LVS失去心跳後,備LVS能夠做爲熱備當即替換。
容災主要是靠KeepAlived來作的。