一文讀懂負載均衡之LVS
作者:說好不能打臉
原文:https://blog.csdn.net/yinwenjie/article/details/46845997
1、LVS介紹
請自行Google或者百度。
2、網絡協議基礎知識
根據官方文檔LVS支持三種負載工作方式:NAT方式、TUN方式和DR方式。為了說明這三種方式的工作原理,我們首先需要了解一下基礎的IP/TCP報文(注意,IP報文和TCP報文是兩種不同的報文格式),以及鏈路層對IP數據的封裝方式。然后我們采用看圖說話的方式,以圖文結合的方式為您介紹這三種工作方式中對報文或重寫或封裝的過程。
為了說清楚我們將要講解的基礎知識,就要提到OSI7層網絡模型。
章文嵩博士及其團隊是我的偶像,LVS體系之所以高效是因為其直接對鏈路層報文、IP報文、TCP報文進行了修改或封裝。所以要真正理解LVS的三種工作方式,就不能像網絡上的抄襲貼一樣轉幾句不知所以的文字就完了,必須對鏈路層報文、網絡層報文、傳輸層報文有所了解。下面我們就進行概述。
為了保證這個系列的博文不發生偏差,我們只講解其中需要用到的屬性和含義,如果讀者對網絡的核心原理有興趣,可以讀讀《TCP/IP詳解,卷1:協議》這本書。
2.1、鏈路層報文
鏈路層的數據格式有一個共同特點,都包括目標MAC地址和源MAC地址。下面這個圖主要說明了我們最常用的Ethernet幀(以太幀)的報文格式:
- 目標MAC地址/源MAC地址:00:00:00:00:00:00——FF:FF:FF:FF:FF:FF這個范圍是全球MAC地址的可用范圍。一張物理網卡肯定有一個唯一的MAC地址。實際上網絡層常用的IP協議,就是基於MAC地址的。一個子網范圍內某個IP對應的MAC地址是通過ARP查詢協議從NAT設備(可能是路由器、交換機或者網絡代理設備)上查詢得到的。
- 上層協議類型:鏈路層的報文是為了承載網絡層的協議而存在的,所以鏈路層的數據格式中需要有一個屬性說明這個鏈路層所承載的上層協議是什么類型。
- IPv4: 0x0800
- ARP:0x0806
- PPPoE:0x8864
- IPV6: 0x86DD
- 封裝的上層數據:最多可以有1500個字節。
請記住這個鏈路層的數據格式,因為講到LVS-DR方式的時候,主要就是對鏈路層的數據格式進行修改,而不會對IP數據報文和TCP數據報文進行修改。
2.2、網絡層IP報文
- TCP協議和IP協議是兩種不同的協議。對應的,也就是兩種不同的描述格式。
- IP協議是網絡層協議,顧名思義,就是用來描述整個網絡構成情況的;TCP協議是通訊層協議,是用來表示兩個或多個網絡上的點如何進行通信和當前通信狀態的。
- 這兩種協議有很多共同特點,例如這兩種協議都分為“頭部”和“數據部”;針對IP協議來說,TCP協議的描述就存放在其“數據部”。
我們首先來看看IP協議是怎么描述的:
好吧,圖我是直接從百度百科直接粘過來的,因為要我來畫,結構也是這樣^_^。其中有幾個重要的我們后面要使用的屬性,要給大家說一下:
- header.version:IP協議的版本號,你猜對了就是IPV4還是IPV6。4表示IPV4版本,6表示IPV6。你要問我什么是IPV4,還是IPV6:192.168.220.141,這就是IPV4的格式;FE80:0000:0000:0000:AAAA:0000:00C2:0002,這就是IPV6的格式。
- header.Total Length:總長度,這個總長度是IP頭和IP數據兩個區域的總長度。主要還是用於生成頭驗證碼和為了操作系統處理方便。
- header.IP Flags:這個位置有3位000,但實際只有后兩位才有值010,這個就是“D”位=1,這個時候表示由於要傳輸的整個數據不大,所以這個IP數據報的數據部分已經描述了整個數據描述,不需要進行IP數據報的分片;”D”為=0,表示要傳輸的整個數據比較大,所以IP數據報進行了拆分,這個時候就要用到最后一位了:最后一位“M”中“1”表示還有后續分片;0表示這個數據報就是IP分片的最后一個數據片了。
- header.Protocol:IP協議是網絡層協議,在網絡層以上是傳輸層協議。TCP、UDP、ICMP和IGMP是傳輸層協議。這個位置的8位說明IP協議數據部分攜帶的是哪種上層協議。
- header.Source Address:這個當然就是IP數據報的來源地址咯。
- header. Destination Address:這個當然就是IP數據報的目標地址咯。
- header.checksum:首部校驗值。這個值校驗IP數據報首部的傳輸完整性(注意校驗不包括IP數據報的數據部分)。這就意味着NAT設備重寫這個數據報的來源或者目標IP后,校驗值要重新進行計算。Source Address、Destination Address、Checksum是各種NAT設備主要的改寫屬性。而且很多時候NAT設備只改寫這三個值就可以實現IP數據報的轉發(當然TCP報文中的端口也會被改寫,以便在端口映射的情況下進行端口轉換)。
2.3、傳輸層TCP報文
上文已經說過,TCP的報文信息是裝在到IP報文的數據部分的,當成網絡上進行傳輸的數據從Srouce Address傳到Destination Address中。下面是TCP報文的信息:
- 頭.源端口號:TCP信息來源的端口號。
- 頭.目的端口號:TCP信息數據的目標端口。
- 頭.狀態位(URG/ACK/PSH/RST/SYN/FIN):如果您已經看到我之前寫的《標准Web系統的架構分層》(http://blog.csdn.net/yinwenjie/article/details/46480485)這邊文章的第3.2小節,那么您對ACK、SYN、FIN這三個標記肯定不陌生,因為TCP的三次握手和連接中斷就要用到這三個標記,需要注意SYN SEQ和ACK SEQ就是TCP數據報的確認號;另外解釋一下PSH和RST兩個狀態標記。應用層的TCP數據報有一個緩存區,也就是說多個正確的TCP數據報會首先放到這個緩存區,達到一定條件后,再推送給上層的應用層協議,例如http。PSH為1的時候,表示不需要再等到后續的TCP數據報文了,直接將目前接收方緩存中的tcp數據報進行數據段組合后推送給上層協議,並且清空緩存區;RST表示復位,您可以理解成放棄當前緩存區的所有未發送給上層協議的TCP數據報文,一般這種情況都是TCP報文傳輸出現了問題。
- 頭.TCP校驗和:TCP報文的校驗和比起IP頭校驗要稍微復雜點。TCP校驗的輸入包括三部分:TCP偽首部、TCP首部長度和TCP數據部長度。TCP偽首部是一個虛擬概念,它包括承載TCP數據報文的IP報文的一部分,和TCP首部的一部分數據(源IP、目標IP、IP報文中的protocoly、以及TCP報文的報文頭長度和TCP報文的數據長度)。
從上面的描述可以看出,一旦IP報文中的源IP和目標IP發生改變了,TCP報文校驗信息就會改變。
3、LVS的三種工作方式
3.1、LVS-NAT工作方式
NAT方式是一種由LVS Master服務節點收到數據報,然后轉給下層的Real Server節點,當Real Server處理完成后回發給LVS Master節點然后又由LVS Master節點轉發出去的工作方式。LVS的管理程序IPVSADMIN負責綁定轉發規則,並完成IP數據報文和TCP數據報文中屬性的重寫。請用幾分鍾時間仔細看看下圖:
- 1、在正式的機房環境中,一般有兩種方式為一個機器分配外網地址:在核心交換機上直接綁定外網地址到主機網卡的,這樣使用ifconfig命令看到的IP地址為外網地址;在核心交換機上使用映射規則,將一個外網地址映射到內網地址,這樣使用ifconfig命令看到的IP地址為內網地址。上圖中我們采用的是后一種映射規則。如果使用前一種外網IP的分配規則,也不會影響LVS NAT的工作方式,因為這個IP被限制在LVS NAT工作以外。只不過eth1的IP從192.168.100.10換成100.64.92.199而已。
- 2、我們用中文描述一下轉換規則:凡是發送到“192.168.100.10:80”的數據報,目標地址全部改寫為“192.168.220.121:8080”,所以來自於100.64.92.199:80的報文被改寫了。被改寫的屬性包括:IP.header.destinationIP、IP.header.checksum、TCP.header.sourcePort、TCP.header.targetPort、TCP.header.checksum。注意IP報文的Source IP不會發生變化,還是“互聯網某個IP”。
- 3、這個包最終被送到了192.168.220.121的8080端口進行處理,並由下層的Real Server生成了返回的數據報(至於這個Real Server是不是“真正的Real Server”,LVS不會關心)。你要問它是怎么被發送過去的,請參考ARP查詢協議。
- 4、注意:因為LVS服務器和Real Server(可能有多個),組成了一個封閉的局域網。除了LVS節點以外,這個子網的任何節點都是無法訪問外網的。所以要求192.168.220.121這個Real Server直接把數據報給“互聯網某個IP”這個外網地址,顯然是不行的,因為在局域網中根本就找不到這個IP。Real Server只能將數據報返給網關,再由網關去尋找這個外網地址。整個服務器中只有LVS節點能夠找到這個外網地址,這就是為什么在LVS-NAT工作模式下,所有的Real Server節點必須設置自己的Gateway為LVS節點的原因。
- 5、收到來源於“192.168.220.121:8080”的數據報文后,IPVS又要進行數據報文的重寫了。重寫規則是:凡是來源於“192.168.220.121:8080”的數據報,源地址全部改寫為“192.168.100.10:80”。於是數據報文的Source IP、Source Port被改寫成“192.168.100.10:80”。在外層的核心交換機(或者是機房以外的請求方)看來,LVS接受了數據報,並進行了處理,返回了結果。它並不知道LVS節點的下層還有什么。
LVS-NAT的優點在於:
- 配置管理簡單。LVS-NAT的工作方式是LVS三種工作模式中最容易理解、最容易配置、最容易管理的工作模式。
- 節省外網IP資源,一般機房分配給使用者的IP數量是有限的,特別是您購買的機架的數量不多時。LVS-NAT工作方式將您的系統架構封裝在局域網中,只需要LVS有一個外網地址或外網地址映射就可以實現訪問了。
- 系統架構相對封閉。在內網環境下我們對防火牆的設置要求不會很高,也相對容易進行物理服務器的運維。您可以設置來源於外網的請求需要進行防火牆過濾,而對內網請求開放訪問。
- 另外改寫后轉給Real Server的數據報文,Real Server並不會關心它的真實性,只要TCP校驗和IP校驗都能通過,Real Server就可以進行處理。所以LVS-NAT工作模式下Real Server可以是任何操作系統,只要它支持TCP/IP協議即可。
- 當然作為Linux系統忠實擁護者,我並不建議使用Window服務器。但如果您的Real Server是.Net系統,又有業務場景需要用到LVS,那么LVS-NAT可能是一個不錯的選擇。
LVS-NAT的缺點是由於這種轉發模式本身所造成的:
- 轉發點就是瓶頸點。您可以想象100台Real Server將處理結果全部轉到一個LVS進行發送是一個怎么樣的場景。事實上,LVS-NAT的極限負載是達不到100台Real Server的。
3.2、LVS-DR工作方式
LVS的DR工作模式,是目前生產環境中最常用的一種工作模式,網上的資料也是最多的,有的文章對DR工作模式的講解還是比較透徹的。這里我們通過圖文的方式再向您介紹一下DR的工作模式(同樣,如果看不清楚,請右鍵“查看原圖”):
上圖反映了DR模式的整個工作過程,同樣為了簡單起見,這里的Real Server也只畫了一個。如果是多個Real Server的話,LVS會通過調度算法來決定發往哪台Real Server。LVS-DR工作模式的幾個關鍵點在於:
- 被Real Server處理后形成的響應報文,不再回發到LVS節點,而是直接路由給中心交換機然后發送出去。省去了LVS-NAT方式中的LVS回發過程。
- LVS節點只會改寫鏈路層的報文封裝,對網絡層和傳輸層報文是不進行改寫的。
- 有網帖說DR工作模式,不能跨子網,也就是說LVS節點和各個Real Server節點必須處於同一個網段中。這是為什么呢?事實又真的是這樣嗎?很多網絡帖子沒有回答這個問題,這篇文章馬上回答一下(實際上章文嵩先生已經回答過這個問題)。
- 使用DR模式時,需要Real Server設置LVS上的VIP為自己的一個回環IP,不然包會被丟棄。這又是為什么呢?很多網貼同樣沒有回答這個問題,好吧,我們馬上回答一下。
先來說一說上圖的工作原理:
- 1、同樣的,我們為了演示整個生產環境中,從機房中心交換機收到一個數據報文后開始講解。中心交換機同樣采取的IP映射方式。但是與LVS-NAT方式不一樣,Real Server在機房的中心交換機上也需要綁定一個外網映射。這樣保證Real Server回發的響應報文能夠被發送到外網。
- 2、LVS節點接收到請求報文后,會改寫報文的數據鏈路層格式。將Target Mac改寫成Real Server的Mac,但是網絡層和傳輸層報文不會改寫,然后重新回發給交換機。這里就涉及一個問題,現在target Mac和Destination IP的對應關系的錯誤的,這個數據報文到了交換機后,由於這種錯位的關系,是不能進行三層交換的,只能進行二層交換(一旦進行IP交換,數據報文的驗證就會出錯,被丟棄)。所以LVS-DR方式要求Real Server和LVS節點必須在同一個局域網內,或者這樣說更確切:LVS節點需要找到一個二層鏈路,將改寫了Mac地址的報文發送給Real Server,而不能進行三層交換的校驗。這樣來看,實際上LVS節點和Real Server界面不一定要在同一個子網,您用一個獨立網卡獨立組網,傳送報文也是可行的。
- 3、通過二層交換,數據被發送到Real Server節點。那么Real Server節點怎么來判斷這個包的正確性呢?首先當然是傳輸層TCP/IP報文校驗沒有問題,LVS-NAT沒有改寫TCP/IP,當然校驗就沒有問題(除非報文本身就存在問題);然后是鏈路層的MAC地址能夠被識別,這時就是回環IP的功勞了。對於Real Server節點來說,192.168.100.10這個VIP就是自己的回環IP,綁定的MAC也就是被LVS替換后的target mac。那么Real Server會認為這個包是在本機運行的某一個應用程序通過回環IP發給自己的,所以這個包不能被丟棄,必須處理。
- 4、被處理后的生成的響應報文,被直接發送給網管。這個就沒有太多的解釋的了,只要保證Real server的默認路由設置成到核心交換機的192.168.100.1就OK了。另外,需要說明的是,由於LVS-DR模式並沒有更改原有的IP報文和TCP報文,所以LVS-DR模式本身是不支持端口映射的,實際上在日常使用實踐中,我們一般使用Nginx做端口映射,因為: 靈.活.。
LVS-DR工作模式的優點在於:
- 解決了LVS-NAT工作模式中的轉發瓶頸問題,能夠支撐規模更大的負載均衡場景。
- 比較耗費網外IP資源,機房的外網IP資源都是有限的,如果在正式生產環境中確實存在這個問題,可以采用LVS-NAT和LVS-DR混合使用的方式來緩解。
LVS-DR當然也有缺點:
- 配置工作較LVS-NAT方式稍微麻煩一點,您至少需要了解LVS-DR模式的基本工作方式才能更好的指導自己進行LVS-DR模式的配置和運行過程中問題的解決。
- 由於LVS-DR模式的報文改寫規則,導致LVS節點和Real Server節點必須在一個網段,因為二層交換是沒法跨子網的。但是這個問題針對大多數系統架構方案來說,實際上並沒有本質限制。
3.3、LVS-TUN工作方式
很多網絡上的文章都為讀者介紹DR和TUN的工作方式類似,要么就是直接講解DR模式和TUN模式的安裝配置方式,然后總結兩種模式類似。那為什么有了DR模式后還需要TUN模式呢?為什么ipvsadmin針對兩種模式的配置參數不一樣呢?
實際上LVS-DR模式和LVS-TUN模式的工作原理完全不一樣,工作場景完全不一樣。DR基於數據報文重寫,TUN模式基於IP隧道,后者是對數據報文的重新封裝。下面我們就來講解一下LVS-TUN模式的工作原理。
首先要介紹一個概念IPIP隧道。將一個完整的IP報文封裝成另一個新的IP報文的數據部分,並通過路由器傳送到指定的地點。在這個過程中路由器並不在意被封裝的原始協議的內容。到達目的地點后,由目的地方依靠自己的計算能力和對IPIP隧道協議的支持,打開封裝協議,取得原始協議。如下圖:
可以說隧道協議就是為了解決跨子網傳輸准備的,在生產環境中由於業務需要、技術需要或者安全需要,可能使用交換機進行VLAN隔離(即形成若干個虛擬的獨立的局域網),我們可能需要LVS節點在局域網A,而需要進行負載的多台Mysql讀服務器可能在局域網B中。這個時候,我們就要配置LVS的隧道方式。LVS-TUN模式如下圖所示(注意,目標節點要能夠解開隧道協議,好消息是Linux支持IPIP隧道協議):
上圖中的線優點多,您只需要關注關心“有箭頭”的虛線就可以了。
- 1、一旦LVS節點發現來目標為192.168.100.10VIP的請求,就會使用IPIP隧道協議對這個請求報文進行封裝。而不是像LVS-DR模式重寫數據報文的MAC信息。如果配置了多個Real Server,那么LVS會使用設置的調度算法確定一個Real Server(這里為了簡單,就只畫了一個Real Server節點)。
- 2、重新封裝后的IPIP隧道協議報文會重新被回發到路由器,路由器(或三層交換機)會根據設置的LVAN映射情況,找到目標服務器,並將這個IPIP隧道報文發送過去。
- 3、Real Server收到這個IPIP隧道報文后,會將這個報文進行解包。這里注意一下,一般情況下IPIP隧道報文會進行分片,就如同IP報文分片一樣,只是為了講解方便,我們假定這個報文不需要分片。解壓后得到的數據報文就是原來發送給VIP的請求報文。
- 4、Real Server設置的回環IP,讓Real Server認為原始的請求報文是從自己本地的某個應用程序發出的,完成原始報文的校驗后,它會對這個報文進行處理。剩下的過程就和LVS-DR相同了,這里就不再進行復述了。
可以說LVS-TUN方式基本上具有LVS-DR的優點。在此基礎上又支持跨子網間穿透。這樣的敷在方案能夠給我們架構師足夠的系統設計場景。
4、LVS調度方式
在本文第3節中,為了集中介紹LVS的三種工作模式,我們在三幅圖中都為LVS畫了一個Real Server。但實際應用中,一般都是多個Real Server。LVS使用多種調度算法來決定“當前的數據報文”由哪個Real Server進行處理。在我的上篇文章《架構設計:負載均衡層設計方案(2)——Nginx安裝》(http://blog.csdn.net/yinwenjie/article/details/46620711)中,已經花了較多的篇幅介紹了Nginx中的調度方式,並明確說明了這些調度方式是萬變不離其宗的。
文章中包括了Hash算法,並且說明了任何屬性都可以做Hash,包括IP、用戶名等;還介紹了輪詢和加權輪詢,加權輪詢也可以依據各種屬性作為權值,例如節點的CPU使用情況、內存使用情況、或者管理員自己設置的一個固定權值。LVS的調度也是這樣的。
- 利用一致性Hash算法完成調度
- 目標地址Hash(DH):調度算法根據請求的目標IP地址,作為散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
- 原地址Hash(SH):根據請求的源IP地址,作為散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。
- 輪詢調度
- 最簡輪詢(RR):調度算法將外部請求按順序輪流分配到集群中的真實服務器上,它均等地對待每一台服務器,而不管服務器上實際的連接數和系統負載。
- 最少連接輪詢(LC):請注意“最少連接輪詢”和“最少連接加權輪詢”兩種調度算法的區別。調度器通過“最少連接”調度算法動態地將網絡請求調度到已建立的鏈接數最少的服務器上。注意請求肯定會被分配到這台目前連接數最少的Real Server上面,不會考慮幾率問題
- 加權輪詢調度:
- 性能加權輪詢(WRR):調度算法根據真實服務器的不同處理能力來調度訪問請求。這樣可以保證處理能力強的服務器能處理更多的訪問流量。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值。
- 最少連接數的加權輪詢(WLC):具有較高權值的服務器將承受較大比例的活動連接負載。調度器可以自動問詢真實服務器的負載情況,並動態地調整其權值。注意,是按照一個比例,有較高的分配幾率,而不是LC一樣“肯定分配”。
在LVS官方中文資料中,提到了更為完整的調度算法。可以進行參考(http://zh.linuxvirtualserver.org/node/2903)。但一定記住各種調度算法肯定是逃不開哈希一致性、輪詢、加權輪詢這大思路的。
