http://www.360doc.com/content/14/0726/00/11962419_397102114.shtml
LVS的全稱Linux vitual system,是由目前阿里巴巴的著名工程師章文嵩博士開發的一款開源軟件。LVS工作在一台server上提供Directory(負載均衡器)的功能,本身並不提供服務,只是把特定的請求轉發給對應的realserver(真正提供服務的主機),從而實現集群環境中的負載均衡。
LVS的核心組件ipvs工作在kernel中,是真正的用於實現根據定義的集群轉發規則把客戶端的請求轉發到特定的realserver。而另一個組件ipvsadm是工作在用戶空間的一個讓用戶定義ipvs規則的工具。故我們只要在server上裝了ipvsadm軟件包就可以定義ipvs規則,而在linux kernel的2.6版本之后kernel是直接支持ipvs的。
注:由於ipvs是接受netfilter五個鈎子函數的中的local_in函數控制的。故ipvs不能和netfilter的一些控制規則同時使用。
好了,進入正題,以下是今天所分享的主要內容:
LVS三種模型LVS-NAT2,LVS-DR,LVS-TUN的工作原理及環境搭建。
實驗環境:redhat enterprise 5.4+ipvsadm+httpd(用於提供web服務)
這些為LVS環境搭建中的一些專業名詞:
RIP:realserver的ip地址
DIP:director的ip地址
CIP:用戶客戶端的ip地址
VIP:虛擬ip地址(這個ip地址是用戶請求的提供服務的ip地址)
一,LVS-NAT
工作原理圖:
工作原理:
圖3.1:VS/NAT的體系結構
客戶通過Virtual IP Address(虛擬服務的IP地址)訪問網絡服務時,請求報文到達調度器,調度器根據連接調度算法從一組真實服務器中選出一台服務器,將報文的目標地址Virtual IP Address改寫成選定服務器的地址,報文的目標端口改寫成選定服務器的相應端口,最后將修改后的報文發送給選出的服務器。同時,調度器在連接Hash表中記錄這個連接,當這個連接的下一個報文到達時,從連接Hash表中可以得到原選定服務器的地址和端口,進行同樣的改寫操作,並將報文傳給原選定的服務器。當來自真實服務器的響應報文經過調度器時,調度器將報文的源地址和源端口改為Virtual IP Address和相應的端口,再把報文發給用戶。我們在連接上引入一個狀態機,不同的報文會使得連接處於不同的狀態,不同的狀態有不同的超時值。在TCP連接中,根據標准的TCP有限狀態機進行狀態遷移;在UDP中,我們只設置一個UDP狀態。不同狀態的超時值是可以設置的,在缺省情況下,SYN狀態的超時為1分鍾,ESTABLISHED狀態的超時為15分鍾,FIN狀態的超時為1分鍾;UDP狀態的超時為5分鍾。當連接終止或超時,調度器將這個連接從連接Hash表中***。
這樣,客戶所看到的只是在Virtual IP Address上提供的服務,而服務器集群的結構對用戶是透明的。對改寫后的報文,應用增量調整Checksum的算法調整TCP Checksum的值,避免了掃描整個報文來計算Checksum的開銷。
特點:
1,所有的realserver和director要在同一個網段內
2,VIP生產環境為公網ip,而DIP用於和rs通信
3,director同時處理請求和應答數據包
4,realserver的網關要指向DIP
5,可以實現端口映射
6,realserver可以是任意操作系統
7,director很可能成為系統性能瓶頸
實驗拓撲:
Director這台server為雙網卡eth0用於客戶端的請求,而eth1用於和realserver通信。
客戶端通過請求172.16.30.1提供web服務。請根據拓撲配置好網絡。
1,rs1上的配置:
配置好rs1上的yum源,可以指向我們的系統安裝光盤。
rs1是作為一台realserver使用,故需要安裝httpd提供web服務:
# yum -y install httpd
添加測試頁:
# cd /var/www/html
# vim index.html
添加如下內容:
jia's server1
啟動httpd服務:
# service httpd start
測試rs1上的web服務:
路由的配置:
# route add default gw 192.168.1.1
2,rs2上的配置:
配置好rs2上的yum源,可以指向我們的系統安裝光盤。
rs2是作為一台realserver使用,故需要安裝httpd提供web服務:
# yum -y install httpd
添加測試頁:
# cd /var/www/html
# vim index.html
添加如下內容:
jia's server2
啟動httpd服務:
# service httpd start
測試rs2上的web服務:
路由的配置:
# route add default gw 192.168.1.1
3,director上的配置:
安裝ipvsadm軟件包:(ipvsadm在安裝光盤的Cluster目錄中,請確認yum源指向)
# yum -y install ipvsadm
打開本機的路由轉發功能:
先查看路由轉發是否打開:
# cat /proc/sys/net/ipv4/ip_forward
如果顯示值為1,則打開,可以跳過此步驟。如果值為0,則開啟此功能。
開啟路由轉發:
# sysctl -w net.ipv4.ip_forward=1 (臨時生效)
可以修改配置文件使其永久生效:
# vim /etc/sysctl.conf
修改net.ipv4.ip_forward = 0此行為net.ipv4.ip_forward = 1即可
使用ipvsadm對ipvs進行配置,由於ipvs的十種算法中,wlc算法是最優算法,也是默認算法,故我們僅以此為例進行配置:
# ipvsadm -A -t 172.16.30.1:80 -s wlc
# ipvsadm -a -t 172.16.30.1:80 -r 192.168.1.10 –m –w 3
# ipvsadm -a -t 172.16.30.1:80 -r 192.168.1.11 –m –w 1
查看配置是否生效:
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.30.1:80 wlc
-> 192.168.1.11:80 Masq 1 0 0
-> 192.168.1.10:80 Masq 3 0 0
ok,我們的LSV-NAT配置好了,下面我們來對其進行測試:
我們可以多刷新頁面獲取效果或換個瀏覽器。
為了更好的演示效果,我們可以用另一台server對httpd服務進行壓力測試:
# ab -c 100 -n 10000 http://172.16.30.1/index.html (ab工具是apache自帶壓力測試工具)
在director上查看請求響應結果:
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.30.1:80 wlc
-> 192.168.1.11:80 Masq 1 16 4194
-> 192.168.1.10:80 Masq 3 62 3997
由於我們使用的是wlc算法,且權重比為3:1,故活動連接數的比幾乎也為3:1。使用不同的調度算法,顯示的結果是不一樣的。
二,LVS-DR(生產環境下應用最為廣泛)
工作原理圖:
工作原理:基於直接路由來實現。當一個client發送一個WEB請求到VIP,LVS服務器根據VIP選擇對應的real-server的Pool,根據算法,在Pool中選擇一台 Real-server,LVS在hash表中記錄該次連接,然后將client的請求包發給選擇的Real-server,最后選擇的Real- server把應答包直接傳給client;當client繼續發包過來時,LVS根據更才記錄的hash表的信息,將屬於此次連接的請求直接發到剛才選 擇的Real-server上;當連接中止或者超時,hash表中的記錄將被***。DR模式在轉發client的包時,只修改了包目的MAC地址為選定的Real-server的mac地址,所以如果LVS和Real-server在不同的廣播域內,那么Real-server就沒辦法接收到轉發的包。這個方式是三種調度中性能最好的,也是我們生產環境中使用最多的。
特點:
1,集群節點和director必須在一個物理網絡內
2,RIP可以使用公網地址或私有地址
3,director僅處理入站請求
4,集群節點網關不指向director,故出站不經過director
5,不支持端口映射
6,大多數操作系統可以作為realserver,要支持隔離arp廣播
7,director服務器的壓力比較小
實驗拓撲:
director只需要一個網卡eth0即可,把VIP配置在eth0的別名eth0:0上即可。我們通過VIP地址192.168.1.1給用戶提供web服務。
注:生產環境下VIP應該是一個公網ip地址
1,rs1上的配置:
配置好rs1上的yum源,可以指向我們的系統安裝光盤。
rs1是作為一台realserver使用,故需要安裝httpd提供web服務:
# yum -y install httpd
添加測試頁:
# cd /var/www/html
# vim index.html
添加如下內容:
jia's server1
啟動httpd服務:
# service httpd start
由於DR模型在內網中基於mac地址進行轉發請求數據包,並且我們的director和realserver都配有一個VIP地址,故我們要限制realserver的arp通告和arp響應級別,以保證我們數據包能到達director指定要發送的realserver。而我們的linux系統提供了這樣的功能,通過修改kernel的兩個參數來控制arp的級別。
兩個重要的arp參數:
arp_announce = 2
表示忽略使用要發送的ip數據包的源地址來設置ARP請求的源地址,而由系統來選擇最好的接口來發送。首要是選擇所有的網絡接口的子網中包含該目標IP地址的本地地址。 如果沒有合適的地址被發現,將選擇當前的要發送數據包的網絡接口或其他的有可能接受到該ARP回應的網絡接口來進行發送。而Linux默認情況下,是使用要發送的ip數據包中的源ip地址作為arp請求的源地址,而默認這種方式對lvs是不是適用的,具體問題為:rs會把自己的vip作為arp請求的源地址,而路由器收到這個arp請求就會更新自己的arp緩存,修改vip對應的mac為rs的,這樣就會造成ip欺騙了,正在lvs上的VIP被搶奪,所以就會有問題。
arp_ignore = 1
表示如果此server接受的arp請求的目的地址,不是該arp請求包進入的接口配置的ip地址,那么不回應此arp請求。(如果lvs的vip配置在rs的eth0:1邏輯網口,這個arp_ignore將失去作用。因為任何設備發送對vip的arp廣播,數據包也會從rs的eth0進入,那么rs上的vip由於在eth0:1上,所以就會對此arp請求就行response,導致網絡混亂)
配置如下:
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
配置lo別名,並且定義lo:0的廣播域為本網卡,使VIP不能向網絡內發送廣播,以防止網絡出現混亂:
# ifconfig lo:0 192.168.1.1 broadcast 192.168.1.1 netmask 255.255.255.255
測試rs1上的web服務:
rs2上的配置:
和rs1上的配置完全一樣,這里不再闡述。
測試rs2的web服務:
director上的配置:
配置好yum源,安裝ipvsadm
# yum install ipvsadm
# ifconfig eth0:0 192.168.1.1 broadcast 192.168.1.1 netmask 255.255.255.255
# route add -host 192.168.1.1 dev eth0:0
# echo 1 > /proc/sys/net/ipv4/ip_forward
以上的配置我們上邊已經闡述配置理由
配置ipvs集群服務:
# ipvsadm -A -t 192.168.1.1:80 -s wlc
# ipvsadm -a -t 192.168.1.1:80 -r 192.168.1.10 –g –w 10
# ipvsadm -a -t 192.168.1.1:80 -r 192.168.1.11 –g –w 5
查看:
# 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.1:80 wlc
-> 192.168.1.11:80 Route 5 0 0
-> 192.168.1.10:80 Route 10 0 0
好了,LVS-DR模型搭建好了,我們來測試一下:
由於我們制定的調度算法和權重不同,故我們多刷新幾次就有效果了。
我們同樣可以用apache的壓力測試工具ab來測試httpd,從而得到調度算法的效果,方法和LVS-NAT的一樣,不在闡述。
三,LVS-TUN
由於LVS-TUN的模型用的不廣泛,如果網絡不好會有很多瓶頸,一般沒有企業使用,故這里不在探討它的配置過程,只說一下它的工作原理。
工作原理圖:
IP隧道(IP tunneling)是將一個IP報文封裝在另一個IP報文的技術,這可以使得目標為一個IP地址的數據報文能被封裝和轉發到另一個IP地址。IP隧道技術亦稱為IP封裝技術(IP encapsulation)。IP隧道主要用於移動主機和虛擬私有網絡(Virtual Private Network),在其中隧道都是靜態建立的,隧道一端有一個IP地址,另一端也有唯一的IP地址。
工作原理:這種方法通過ip隧道技術實現虛擬服務器。
1> client 發送request包到LVS服務器的VIP上。
2> VIP按照算法選擇后端的一個Real-server,並將記錄一條消息到hash表中,然后將client的request包封裝到一個新的IP包里,新IP包的目的IP是Real-server的IP,然后轉發給Real-server。
3> Real-server收到包后,解封裝,取出client的request包,發現他的目的地址是VIP,而Real-server發現在自己的 lo:0口上有這個IP地址,於是處理client的請求,然后real-server將直接relpy這個request包直接發給client。
4> 該client的后面的request包,LVS直接按照hash表中的記錄直接轉發給Real-server,當傳輸完畢或者連接超時,那么將***hash表中的記錄。
由於通過IP Tunneling 封裝后,封裝后的IP包的目的地址為Real-server的IP地址,那么只要Real-server的地址能路由可達,Real-server在什么 網絡里都可以,這樣可以減少對於公網IP地址的消耗,但是因為要處理IP Tunneling封裝和解封裝的開銷,那么效率不如DR模式。
特點:
1,realserver和director可以不在一個物理網絡中
2,director要有到realserver的路由
3,director僅處理入站請求
4,realserver的網關不能指向DIP
5,不支持端口映射
6,支持ip隧道功能的操作系統才能作為realserver
由於需要Real-server支持IP Tunneling,所以設置與DR模式不太一樣,LVS不需要設置tunl設備,LVS本身可以進行封裝
rs的配置:
只需要配置VIP在tunl設備上即可:(vip:172.16.1.1)
# ifconfig tunl0 172.16.1.1 netmask 255.255.255.255
# ifconfig tunl0
tunl0 Link encap:IPIP Tunnel HWaddr
inet addr:172.16.1.1 Mask:255.255.255.255
UP RUNNING NOARP MTU:1480 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
四,lvs簡單調優
1,調整ipvs connection hash表的大小
IPVS connection hash table size,取值范圍:[12,20]。該表用於記錄每個進來的連接及路由去向的信息。連接的Hash表要容納幾百萬個並發連接,任何一個報文到達都需要查找連接Hash表,Hash表是系統使用最頻繁的部分。Hash表的查找復雜度為O(n/m),其中n為Hash表中對象的個數,m為Hash表的桶個數。當對象在Hash表中均勻分布和Hash表的桶個數與對象個數一樣多時,Hash表的查找復雜度可以接近O(1)。
連接跟蹤表中,每行稱為一個hash bucket(hash桶),桶的個數是一個固定的值CONFIG_IP_VS_TAB_BITS,默認為12(2的12次方,4096)。這個值可以調整,該值的大小應該在 8 到 20 之間,詳細的調整方法見后面。每一行都是一個鏈表結構,包含N列(即N條連接記錄),這個N是無限的,N的數量決定了決定了查找的速度。
LVS的調優建議將hash table的值設置為不低於並發連接數。例如,並發連接數為200,Persistent時間為200S,那么hash桶的個數應設置為盡可能接近200x200=40000,2的15次方為32768就可以了。當ip_vs_conn_tab_bits=20 時,哈希表的的大小(條目)為 pow(2,20),即 1048576,對於64位系統,IPVS占用大概16M內存,可以通過demsg看到:IPVS: Connection hash table configured (size=1048576, memory=16384Kbytes)。對於現在的服務器來說,這樣的內存占用不是問題。所以直接設置為20即可。
關於最大“連接數限制”:這里的hash桶的個數,並不是LVS最大連接數限制。LVS使用哈希鏈表解決“哈希沖突”,當連接數大於這個值時,必然會出現哈稀沖突,會(稍微)降低性能,但是並不對在功能上對LVS造成影響。
調整 ip_vs_conn_tab_bits的方法:
新版的linux kernel中的IPVS代碼,允許調整 ip_vs_conn_bits 的值。而老kernel中的的IPVS代碼則需要通過重新編譯內核來進行調整。
在linux kernel發行版里,IPVS通常是以模塊的形式編譯的。
確認能否調整使用命令 modinfo -p ip_vs(查看 ip_vs 模塊的參數),看有沒有 conn_tab_bits 參數可用。假如可以用,那么說時可以調整,調整方法是加載時通過設置 conn_tab_bits參數:
在/etc/modprobe.d/目錄下添加文件ip_vs.conf,內容為:
options ip_vs conn_tab_bits=20
查看
ipvsadm -l
如果顯示IP Virtual Server version 1.2.1 (size=4096),則前面加的參數沒有生效
modprobe -r ip_vs
modprobe ip_vs
重新查看
IP Virtual Server version 1.2.1 (size=1048576)
假如沒有 conn_tab_bits 參數可用,則需要重新調整編譯選項,重新編譯。
Centos6.2,內核版本2.6.32-220.13.1.el6.x86_64,仍然不支持這個參數,只能自定義編譯了。
另外,假如IPVS支持調整 ip_vs_conn_tab_bits,而又將IPVS集成進了內核,那么只能通過重啟,向內核傳遞參數來調整了。在引導程序的 kernel 相關的配置行上,添加:ip_vs.conn_tab_bits=20 ,然后,重啟。
或者重新編譯內核。
2,linux系統參數優化
關閉網卡LRO和GRO
現在大多數網卡都具有LRO/GRO功能,即 網卡收包時將同一流的小包合並成大包 (tcpdump抓包可以看到>MTU 1500bytes的數據包)交給 內核協議棧;LVS內核模塊在處理>MTU的數據包時,會丟棄;
因此,如果我們用LVS來傳輸大文件,很容易出現丟包,傳輸速度慢;
解決方法,關閉LRO/GRO功能,命令:
ethtool -k eth0 查看LRO/GRO當前是否打開
ethtool -K eth0 lro off 關閉GRO
ethtool -K eth0 gro off 關閉GRO
禁用ARP,增大backlog並發數
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.core.netdev_max_backlog = 500000 (在每個網絡接口接收數據包的速率比內核處理這些包的速率快時,允許送到隊列的數據包的最大數目)
3,lvs自身配置
盡量避免sh算法
一些業務為了支持會話保持,選擇SH調度算法,以實現 同一源ip的請求調度到同一台RS上;但 SH算法本省沒有實現一致性hash,一旦一台RS down,,當前所有連接都會斷掉;如果配置了inhibit_on_failure,那就更悲劇了,調度到該RS上的流量會一直損失;
實際線上使用時,如需 會話保持,建議配置 persistence_timeout參數,保證一段時間同一源ip的請求到同一RS上。
4,手動綁定linux系統網卡中斷
lvs的並發過大,對網卡的利用很頻繁,而對網卡的調優,也能增加lvs的效率。當前大多數系統網卡都是支持硬件多隊列的,為了充分發揮多核的性能,需要手動將網卡中斷(流量)分配到所有CPU核上去處理。默認情況下,網卡的所有的中斷都是發送到一個默認的cpu上去處理的,而cpu中斷需要等待時間,這樣對於使用網卡頻繁的服務,網卡性能就會成為瓶頸。
1,查看網卡中斷:
# cat /proc/interrupts
2,綁定網卡中斷到cpu
例如將中斷52-59分別綁定到CPU0-7上:
[plain] view plaincopy
echo "1" > /proc/irq/52/smp_affinity
echo "2" > /proc/irq/53/smp_affinity
echo "4" > /proc/irq/54/smp_affinity
echo "8" > /proc/irq/55/smp_affinity
echo "10" > /proc/irq/56/smp_affinity
echo "20" > /proc/irq/57/smp_affinity
echo "40" > /proc/irq/58/smp_affinity
echo "80" > /proc/irq/59/smp_affinity
/proc/irq/${IRQ_NUM}/smp_affinity為中斷號為IRQ_NUM的中斷綁定的CPU核的情況。以十六進制表示,每一位代表一個CPU核。
1(00000001)代表CPU0
2(00000010)代表CPU1
3(00000011)代表CPU0和CPU1
3,關閉系統自動中斷平衡:
# service irqbalance stop
4,如果網卡硬件不支持多隊列,那就采用google提供的軟多隊列RPS;
配置方法同硬中斷綁定,例:
# echo 01 > /sys/class/net/eth0/queues/rx-0/rps_cpus
# echo 02 > /sys/class/net/eth0/queues/rx-1/rps_cpus