天天看點

LVS的三種轉發模型及簡單調優

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

工作原理圖:

<a href="http://blog.51cto.com/attachment/201204/153355337.jpg" target="_blank"></a>

工作原理:

圖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很可能成為系統性能瓶頸

實驗拓撲:

<a href="http://blog.51cto.com/attachment/201204/153504890.jpg" target="_blank"></a>

Director這台server為雙網卡eth0用于用戶端的請求,而eth1用于和realserver通信。

用戶端通過請求172.16.30.1提供web服務。請根據拓撲配置好網絡。

1,rs1上的配置:

配置好rs1上的yum源,可以指向我們的系統安裝CD光牒。

rs1是作為一台realserver使用,故需要安裝httpd提供web服務:

# yum -y install httpd

添加測試頁:

# cd /var/www/html

# vim index.html

添加如下内容:

jia's server1

啟動httpd服務:

# service httpd start

測試rs1上的web服務:

<a href="http://blog.51cto.com/attachment/201204/153709323.jpg" target="_blank"></a>

路由的配置:

# route add default gw 192.168.1.1

2,rs2上的配置:

配置好rs2上的yum源,可以指向我們的系統安裝CD光牒。

rs2是作為一台realserver使用,故需要安裝httpd提供web服務:

jia's server2

測試rs2上的web服務:

<a href="http://blog.51cto.com/attachment/201204/153802824.jpg" target="_blank"></a>

3,director上的配置:

安裝ipvsadm軟體包:(ipvsadm在安裝CD光牒的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

-&gt; RemoteAddress:Port      Forward Weight ActiveConn InActConn

TCP 172.16.30.1:80 wlc

-&gt; 192.168.1.11:80       Masq  1   0     0    

-&gt; 192.168.1.10:80       Masq  3   0     0

ok,我們的LSV-NAT配置好了,下面我們來對其進行測試:

我們可以多重新整理頁面擷取效果或換個浏覽器。

<a href="http://blog.51cto.com/attachment/201204/153922666.jpg" target="_blank"></a>

為了更好的示範效果,我們可以用另一台server對httpd服務進行壓力測試:

# ab -c 100 -n 10000 http://172.16.30.1/index.html (ab工具是apache自帶壓力測試工具)

在director上檢視請求響應結果:

-&gt; 192.168.1.11:80       Masq  1   16     4194  

-&gt; 192.168.1.10:80       Masq  3   62     3997

由于我們使用的是wlc算法,且權重比為3:1,故活動連接配接數的比幾乎也為3:1。使用不同的排程算法,顯示的結果是不一樣的。

二,LVS-DR(生産環境下應用最為廣泛)

<a href="http://blog.51cto.com/attachment/201204/154239621.jpg" target="_blank"></a>

工作原理:基于直接路由來實作。當一個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伺服器的壓力比較小

<a href="http://blog.51cto.com/attachment/201204/200225774.jpg" target="_blank"></a>

director隻需要一個網卡eth0即可,把VIP配置在eth0的别名eth0:0上即可。我們通過VIP位址192.168.1.1給使用者提供web服務。

注:生産環境下VIP應該是一個公網ip位址

由于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 &gt; /proc/sys/net/ipv4/conf/lo/arp_ignore

# echo 2 &gt; /proc/sys/net/ipv4/conf/lo/arp_announce

# echo 1 &gt; /proc/sys/net/ipv4/conf/all/arp_ignore

# echo 2 &gt; /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

<a href="http://blog.51cto.com/attachment/201204/154411224.jpg" target="_blank"></a>

rs2上的配置:

和rs1上的配置完全一樣,這裡不再闡述。

測試rs2的web服務:

<a href="http://blog.51cto.com/attachment/201204/154453248.jpg" target="_blank"></a>

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 &gt; /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

TCP 192.168.1.1:80 wlc

-&gt; 192.168.1.11:80       Route  5   0     0    

-&gt; 192.168.1.10:80       Route  10   0     0  

好了,LVS-DR模型搭建好了,我們來測試一下:

由于我們制定的排程算法和權重不同,故我們多重新整理幾次就有效果了。

<a href="http://blog.51cto.com/attachment/201204/154547411.jpg" target="_blank"></a>

我們同樣可以用apache的壓力測試工具ab來測試httpd,進而得到排程算法的效果,方法和LVS-NAT的一樣,不在闡述。

三,LVS-TUN

由于LVS-TUN的模型用的不廣泛,如果網絡不好會有很多瓶頸,一般沒有企業使用,故這裡不在探讨它的配置過程,隻說一下它的工作原理。

<a href="http://blog.51cto.com/attachment/201204/154657586.jpg" target="_blank"></a>

IP隧道(IP tunneling)是将一個IP封包封裝在另一個IP封包的技術,這可以使得目标為一個IP位址的資料封包能被封裝和轉發到另一個IP位址。IP隧道技術亦稱為IP封裝技術(IP encapsulation)。IP隧道主要用于移動主機和虛拟私有網絡(Virtual Private Network),在其中隧道都是靜态建立的,隧道一端有一個IP位址,另一端也有唯一的IP位址。

工作原理:這種方法通過ip隧道技術實作虛拟伺服器。

1&gt; client 發送request包到LVS伺服器的VIP上。

2&gt; VIP按照算法選擇後端的一個Real-server,并将記錄一條消息到hash表中,然後将client的request包封裝到一個新的IP包裡,新IP包的目的IP是Real-server的IP,然後轉發給Real-server。

3&gt; Real-server收到包後,解封裝,取出client的request包,發現他的目的位址是VIP,而Real-server發現在自己的 lo:0口上有這個IP位址,于是處理client的請求,然後real-server将直接relpy這個request包直接發給client。

4&gt; 該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的路由

4,realserver的網關不能指向DIP

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抓包可以看到&gt;MTU 1500bytes的資料包)交給 核心協定棧;LVS核心子產品在處理&gt;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" &gt; /proc/irq/52/smp_affinity  

echo "2" &gt; /proc/irq/53/smp_affinity  

echo "4" &gt; /proc/irq/54/smp_affinity  

echo "8" &gt; /proc/irq/55/smp_affinity  

echo "10" &gt; /proc/irq/56/smp_affinity  

echo "20" &gt; /proc/irq/57/smp_affinity  

echo "40" &gt; /proc/irq/58/smp_affinity  

echo "80" &gt; /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 &gt; /sys/class/net/eth0/queues/rx-0/rps_cpus

# echo  02 &gt; /sys/class/net/eth0/queues/rx-1/rps_cpus

本文轉自 leejia1989 51CTO部落格,原文連結:http://blog.51cto.com/leejia/834223,如需轉載請自行聯系原作者

繼續閱讀