部份內容轉自:http://www.javashuo.com/article/p-uvphxafg-da.htmlhtml
1、LVS簡介linux
LVS(Linux Virtual Server)即Linux虛擬服務器,是由章文嵩博士主導的開源負載均衡項目,目前LVS已經被集成到Linux內核模塊中。該項目在Linux內核中實現了基於IP的數據請求負載均衡調度方案,其體系結構如圖1所示,終端互聯網用戶從外部訪問公司的外部負載均衡服務器,終端用戶的Web請求會發送給LVS調度器,調度器根據本身預設的算法決定將該請求發送給後端的某臺Web服務器,好比,輪詢算法能夠將外部的請求平均分發給後端的全部服務器,終端用戶訪問LVS調度器雖然會被轉發到後端真實的服務器,但若是真實服務器鏈接的是相同的存儲,提供的服務也是相同的服務,最終用戶不論是訪問哪臺真實服務器,獲得的服務內容都是同樣的,整個集羣對用戶而言都是透明的。最後根據LVS工做模式的不一樣,真實服務器會選擇不一樣的方式將用戶須要的數據發送到終端用戶,LVS工做模式分爲NAT模式、TUN模式、以及DR模式。算法
2、三種工做模式的解析後端
一、基於NAT的LVS模式負載均衡centos
NAT(Network Address Translation)即網絡地址轉換,其做用是經過數據報頭的修改,使得位於企業內部的私有IP地址能夠訪問外網,以及外部用用戶能夠訪問位於公司內部的私有IP主機。VS/NAT工做模式拓撲結構如圖2所示,LVS負載調度器可使用兩塊網卡配置不一樣的IP地址,eth0設置爲私鑰IP與內部網絡經過交換設備相互鏈接,eth1設備爲外網IP與外部網絡聯通。瀏覽器
第一步,用戶經過互聯網DNS服務器解析到公司負載均衡設備上面的外網地址,相對於真實服務器而言,LVS外網IP又稱VIP(Virtual IP Address),用戶經過訪問VIP,便可鏈接後端的真實服務器(Real Server),而這一切對用戶而言都是透明的,用戶覺得本身訪問的就是真實服務器,但他並不知道本身訪問的VIP僅僅是一個調度器,也不清楚後端的真實服務器到底在哪裏、有多少真實服務器。服務器
第二步,用戶將請求發送至124.126.147.168,此時LVS將根據預設的算法選擇後端的一臺真實服務器(192.168.0.1~192.168.0.3),將數據請求包轉發給真實服務器,而且在轉發以前LVS會修改數據包中的目標地址以及目標端口,目標地址與目標端口將被修改成選出的真實服務器IP地址以及相應的端口。網絡
第三步,真實的服務器將響應數據包返回給LVS調度器,調度器在獲得響應的數據包後會將源地址和源端口修改成VIP及調度器相應的端口,修改完成後,由調度器將響應數據包發送回終端用戶,另外,因爲LVS調度器有一個鏈接Hash表,該表中會記錄鏈接請求及轉發信息,當同一個鏈接的下一個數據包發送給調度器時,從該Hash表中能夠直接找到以前的鏈接記錄,並根據記錄信息選出相同的真實服務器及端口信息。負載均衡
二、基於TUN的LVS負載均衡ssh
在LVS(NAT)模式的集羣環境中,因爲全部的數據請求及響應的數據包都須要通過LVS調度器轉發,若是後端服務器的數量大於10臺,則調度器就會成爲整個集羣環境的瓶頸。咱們知道,數據請求包每每遠小於響應數據包的大小。由於響應數據包中包含有客戶須要的具體數據,因此LVS(TUN)的思路就是將請求與響應數據分離,讓調度器僅處理數據請求,而讓真實服務器響應數據包直接返回給客戶端。VS/TUN工做模式拓撲結構如圖3所示。其中,IP隧道(IP tunning)是一種數據包封裝技術,它能夠將原始數據包封裝並添加新的包頭(內容包括新的源地址及端口、目標地址及端口),從而實現將一個目標爲調度器的VIP地址的數據包封裝,經過隧道轉發給後端的真實服務器(Real Server),經過將客戶端發往調度器的原始數據包封裝,並在其基礎上添加新的數據包頭(修改目標地址爲調度器選擇出來的真實服務器的IP地址及對應端口),LVS(TUN)模式要求真實服務器能夠直接與外部網絡鏈接,真實服務器在收到請求數據包後直接給客戶端主機響應數據。
三、基於DR的LVS負載均衡(經常使用模式)
在LVS(TUN)模式下,因爲須要在LVS調度器與真實服務器之間建立隧道鏈接,這一樣會增長服務器的負擔。與LVS(TUN)相似,DR模式也叫直接路由模式,其體系結構如圖4所示,該模式中LVS依然僅承擔數據的入站請求以及根據算法選出合理的真實服務器,最終由後端真實服務器負責將響應數據包發送返回給客戶端。與隧道模式不一樣的是,直接路由模式(DR模式)要求調度器與後端服務器必須在同一個局域網內,VIP地址須要在調度器與後端全部的服務器間共享,由於最終的真實服務器給客戶端迴應數據包時須要設置源IP爲VIP地址,目標IP爲客戶端IP,這樣客戶端訪問的是調度器的VIP地址,迴應的源地址也依然是該VIP地址(真實服務器上的VIP),客戶端是感受不到後端服務器存在的。因爲多臺計算機都設置了一樣一個VIP地址,因此在直接路由模式中要求調度器的VIP地址是對外可見的,客戶端須要將請求數據包發送到調度器主機,而全部的真實服務器的VIP地址必須配置在Non-ARP的網絡設備上,也就是該網絡設備並不會向外廣播本身的MAC及對應的IP地址,真實服務器的VIP對外界是不可見的,但真實服務器卻能夠接受目標地址VIP的網絡請求,並在迴應數據包時將源地址設置爲該VIP地址。調度器根據算法在選出真實服務器後,在不修改數據報文的狀況下,將數據幀的MAC地址修改成選出的真實服務器的MAC地址,經過交換機將該數據幀發給真實服務器。整個過程當中,真實服務器的VIP不須要對外界可見。
3、LVS負載均衡調度算法
根據前面的介紹,咱們瞭解了LVS的三種工做模式,但無論實際環境中採用的是哪一種模式,調度算法進行調度的策略與算法都是LVS的核心技術,LVS在內核中主要實現了一下十種調度算法。
1.輪詢調度
輪詢調度(Round Robin 簡稱'RR')算法就是按依次循環的方式將請求調度到不一樣的服務器上,該算法最大的特色就是實現簡單。輪詢算法假設全部的服務器處理請求的能力都同樣的,調度器會將全部的請求平均分配給每一個真實服務器。
2.加權輪詢調度
加權輪詢(Weight Round Robin 簡稱'WRR')算法主要是對輪詢算法的一種優化與補充,LVS會考慮每臺服務器的性能,並給每臺服務器添加一個權值,若是服務器A的權值爲1,服務器B的權值爲2,則調度器調度到服務器B的請求會是服務器A的兩倍。權值越高的服務器,處理的請求越多。
3.最小鏈接調度
最小鏈接調度(Least Connections 簡稱'LC')算法是把新的鏈接請求分配到當前鏈接數最小的服務器。最小鏈接調度是一種動態的調度算法,它經過服務器當前活躍的鏈接數來估計服務器的狀況。調度器須要記錄各個服務器已創建鏈接的數目,當一個請求被調度到某臺服務器,其鏈接數加1;當鏈接中斷或者超時,其鏈接數減1。
(集羣系統的真實服務器具備相近的系統性能,採用最小鏈接調度算法能夠比較好地均衡負載。)
4.加權最小鏈接調度
加權最少鏈接(Weight Least Connections 簡稱'WLC')算法是最小鏈接調度的超集,各個服務器相應的權值表示其處理性能。服務器的缺省權值爲1,系統管理員能夠動態地設置服務器的權值。加權最小鏈接調度在調度新鏈接時儘量使服務器的已創建鏈接數和其權值成比例。調度器能夠自動問詢真實服務器的負載狀況,並動態地調整其權值。
5.基於局部的最少鏈接
基於局部的最少鏈接調度(Locality-Based Least Connections 簡稱'LBLC')算法是針對請求報文的目標IP地址的 負載均衡調度,目前主要用於Cache集羣系統,由於在Cache集羣客戶請求報文的目標IP地址是變化的。這裏假設任何後端服務器均可以處理任一請求,算法的設計目標是在服務器的負載基本平衡狀況下,將相同目標IP地址的請求調度到同一臺服務器,來提升各臺服務器的訪問局部性和Cache命中率,從而提高整個集羣系統的處理能力。LBLC調度算法先根據請求的目標IP地址找出該目標IP地址最近使用的服務器,若該服務器是可用的且沒有超載,將請求發送到該服務器;若服務器不存在,或者該服務器超載且有服務器處於一半的工做負載,則使用'最少鏈接'的原則選出一個可用的服務器,將請求發送到服務器。
6.帶複製的基於局部性的最少鏈接
帶複製的基於局部性的最少鏈接(Locality-Based Least Connections with Replication 簡稱'LBLCR')算法也是針對目標IP地址的負載均衡,目前主要用於Cache集羣系統,它與LBLC算法不一樣之處是它要維護從一個目標IP地址到一組服務器的映射,而LBLC算法維護從一個目標IP地址到一臺服務器的映射。按'最小鏈接'原則從該服務器組中選出一一臺服務器,若服務器沒有超載,將請求發送到該服務器;若服務器超載,則按'最小鏈接'原則從整個集羣中選出一臺服務器,將該服務器加入到這個服務器組中,將請求發送到該服務器。同時,當該服務器組有一段時間沒有被修改,將最忙的服務器從服務器組中刪除,以下降複製的程度。
7.目標地址散列調度
目標地址散列調度(Destination Hashing 簡稱'DH')算法先根據請求的目標IP地址,做爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且並未超載,將請求發送到該服務器,不然返回空。
8.源地址散列調度U
源地址散列調度(Source Hashing 簡稱'SH')算法先根據請求的源IP地址,做爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且並未超載,將請求發送到該服務器,不然返回空。它採用的散列函數與目標地址散列調度算法的相同,它的算法流程與目標地址散列調度算法的基本類似。
9.最短的指望的延遲
最短的指望的延遲調度(Shortest Expected Delay 簡稱'SED')算法基於WLC算法。舉個例子吧,ABC三臺服務器的權重分別爲一、二、3 。那麼若是使用WLC算法的話一個新請求進入時它可能會分給ABC中的任意一個。使用SED算法後會進行一個運算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把請求交給得出運算結果最小的服務器。
10.最少隊列調度
最少隊列調度(Never Queue 簡稱'NQ')算法,無需隊列。若是有realserver的鏈接數等於0就直接分配過去,不須要在進行SED運算。
4、LVS實驗(DR模式)
1.系統準備
準備三臺虛擬機位於同一局域網,網段爲192.168.1.0。
三臺虛擬機IP分別是:
LVS server:192.168.1.200 (DIP)
Real server 1:192.168.1.201 (RIP)
Real server 2:192.168.1.202 (RIP)
2.配置LVS server的網絡:
給LVS server配置VIP 192.168.1.10(暫時生效)
ifconfig eth0:8 192.168.1.10/24
[root@lvs-server ~]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.200 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 240e:398:c0:ddc0:20c:29ff:fea5:7756 prefixlen 64 scopeid 0x0<global> inet6 fe80::20c:29ff:fea5:7756 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:a5:77:56 txqueuelen 1000 (Ethernet) RX packets 2426 bytes 167928 (163.9 KiB) RX errors 0 dropped 1495 overruns 0 frame 0 TX packets 667 bytes 118207 (115.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0:8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255 ether 00:0c:29:a5:77:56 txqueuelen 1000 (Ethernet) lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 8 bytes 708 (708.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 708 (708.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
配置非本身的包的處理方式(不能用vi修改,暫時生效):
echo 1 > /proc/sys/net/ipv4/ip_forward
3.配置每臺Real server:
修改arp配置,隱藏VIP(不能用vi修改,暫時生效):
# 只響應詢問本身地址的請求,不迴應位於lo的VIP echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore # 只主動播報與本接口地址匹配的信息 echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce # 爲全部網卡添加一樣配置,好比後續添加新的網卡 echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
在real server的環回接口lo上配置VIP(暫時生效):
ifconfig lo:2 192.168.1.10 netmask 255.255.255.255
注意:這裏的VIP和LVS server的VIP是一致的。netmask是255.255.255.255,這是由於若是配置爲255.255.255.0,在路由條目中會與192.168.1.0網段的路由條目衝突。用全1掩碼,就將網段限制爲192.168.1.10一個IP了。
[root@real-server-1 ~]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.201 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 240e:398:c0:ddc0:20c:29ff:fe0a:bb12 prefixlen 64 scopeid 0x0<global> inet6 fe80::20c:29ff:fe0a:bb12 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:0a:bb:12 txqueuelen 1000 (Ethernet) RX packets 1930 bytes 125407 (122.4 KiB) RX errors 0 dropped 1472 overruns 0 frame 0 TX packets 304 bytes 51765 (50.5 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo:2: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 192.168.1.10 netmask 255.255.255.255 loop txqueuelen 1000 (Local Loopback)
爲每臺Real server安裝httpd服務器用於測試:
yum install httpd -y
在httpd的發佈目錄下寫一個簡單的頁面index.html:
cd /var/www/html vi index.html from real-server-1
啓動httpd服務:
systemctl start httpd
使用瀏覽器驗證一下(這時是分別訪問的RIP):
使用VIP訪問一下(此時確定不成功,由於還未配置LVS server):
4.在LVS server上配置LVS服務:
安裝ipvsadm:
yum install ipvsadm -y
由於LVS的代碼被歸入了Linux內核,只提供系統調用。咱們不能直接操做內核,因此須要一個在用戶態的軟件來操做LVS。
使用ipvsadm的命令來配置業務:
# 配置VIP ipvsadm -A -t 192.168.1.10:80 -s rr # 配置後面的兩臺負載服務器 ipvsadm -a -t 192.168.1.10:80 -r 192.168.1.201 -g ipvsadm -a -t 192.168.1.10:80 -r 192.168.1.202 -g
因爲咱們的httpd監聽的是80端口,因此LVS服務也是監聽80端口,IP爲VIP。
查詢ipvsadm的幫助:
# 添加一個虛擬服務 --add-service -A add virtual service with options # 添加一個負載服務器 --add-server -a add real server with options # 虛擬IP地址和監聽端口 --tcp-service -t service-address service-address is host[:port] # 轉發策略,rr爲輪詢 --scheduler -s scheduler one of rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq, the default scheduler is wlc. # real server的IP端口 --real-server -r server-address server-address is host (and port)
配置好後,查看當前配置結果:
[root@lvs-server yum.repos.d]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.10:80 rr -> 192.168.1.201:80 Route 1 0 0 -> 192.168.1.202:80 Route 1 0 0
能夠看到有一個虛擬服務,VIP爲192.168.1.10,監聽端口爲80,轉發策略爲rr輪詢。Real server有兩臺,IP分別是192.168.1.201,192.168.1.202,服務端口也是80。
此時,咱們再使用瀏覽器訪問VIP:
咱們能夠看到訪問成功,而且LVS將該次請求分發給了real-server-2,也就是192.168.1.202。
爲了驗證轉發效果,咱們使用linux的curl來模擬:
[root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-2 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-1 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-2 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-1 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-2 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-1 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-2 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-1 [root@centos-clone1 ~]# curl 192.168.1.10:80 from real-server-2
從模擬結果能夠看出,每次請求確實是在real-server-1和real-server-2之間輪詢。
咱們立刻使用命令查看一下TCP連接狀況:
[root@lvs-server yum.repos.d]# ipvsadm -lnc IPVS connection entries pro expire state source virtual destination TCP 00:53 FIN_WAIT 192.168.1.121:57278 192.168.1.10:80 192.168.1.202:80 TCP 00:55 FIN_WAIT 192.168.1.121:57294 192.168.1.10:80 192.168.1.202:80 TCP 00:54 FIN_WAIT 192.168.1.121:57284 192.168.1.10:80 192.168.1.201:80 TCP 00:54 FIN_WAIT 192.168.1.121:57290 192.168.1.10:80 192.168.1.202:80 TCP 00:53 FIN_WAIT 192.168.1.121:57276 192.168.1.10:80 192.168.1.201:80 TCP 00:50 FIN_WAIT 192.168.1.121:57270 192.168.1.10:80 192.168.1.202:80 TCP 00:54 FIN_WAIT 192.168.1.121:57288 192.168.1.10:80 192.168.1.201:80 TCP 00:52 FIN_WAIT 192.168.1.121:57274 192.168.1.10:80 192.168.1.202:80 TCP 00:52 FIN_WAIT 192.168.1.121:57272 192.168.1.10:80 192.168.1.201:80 TCP 00:54 FIN_WAIT 192.168.1.121:57286 192.168.1.10:80 192.168.1.202:80 TCP 00:53 FIN_WAIT 192.168.1.121:57280 192.168.1.10:80 192.168.1.201:80 TCP 00:55 FIN_WAIT 192.168.1.121:57292 192.168.1.10:80 192.168.1.201:80 TCP 00:54 FIN_WAIT 192.168.1.121:57282 192.168.1.10:80 192.168.1.202:80
能夠看到剛纔創建的TCP連接都已經斷開,但能夠看到都來自於192.168.1.121,端口爲curl的隨機端口,目的是real-server-1和real-server-2。
咱們再來看看lvs-server和兩臺read-server的TCP連接狀況(從新請求幾回):
[root@lvs-server yum.repos.d]# netstat -natp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1145/master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 987/sshd tcp 0 52 192.168.1.200:22 192.168.1.8:60161 ESTABLISHED 1384/sshd: root@pts tcp6 0 0 ::1:25 :::* LISTEN 1145/master tcp6 0 0 :::22 :::* LISTEN 987/sshd
咱們發現,LVS-server上根本沒有創建與192.168.1.121客戶端之間的TCP連接,說明LVS的一個重要特性:只作轉發,而不與客戶端創建4層連接。
5、存在的問題
1.LVS server發生故障時,致使全部用戶沒法訪問業務,由於全部請求都沒法到達real server。
2.Real server發生故障時,請求一樣會分配到宕機的Real server,致使部分用戶沒法訪問業務。
解決方案:
1.利用HA(高可用)方案,解決LVS server的單點故障問題,例如使用多臺LVS服務器構成主備模式。
2.動態的檢測Real server的服務器狀態,當某臺宕機時,動態的從LVS Server的Real server列表中剔除。當發現服務恢復時,自動將其加入列表。
咱們能夠利用keepalived方案來解決以上問題,詳情參見 《Linux——(7)keepalived》