1.3.2 LVS的持久連接機制
LVS是L4層負載均衡器,它自身提供了保持連接機制。
LVS是利用配置文件里的persistence(單位為秒)設置來設定會話保持時間的,這個選項對于電子商務網站來說尤其有用:當用戶遠程用賬號登錄網站時,有了這個會話保持功能,就能把用戶的請求轉發給同一個應用服務器了。在這里,我們來做一個假設,假定現在有一個LVS環境使用LVS/DR轉發模式,真實的Web服務器有2個,LVS負載均衡器不啟用會話保持功能。當用戶第一次訪問的時候,他的訪問請求被負載均衡器轉給某個真實服務器,此時他會看到一個登錄頁面,第一次訪問完畢;接著他在登錄框里填寫用戶名和密碼,然后提交;這時候問題可能就會出現了——登錄不成功。因為沒有會話保持,負載均衡器可能會把第2次的請求轉發到其他的服務器上,這樣瀏覽器又會提醒客戶需要再次輸入用戶名及密碼。所以這里需要通過LVS啟用持久連接機制來實現會話保持功能。
下面做一個簡單的實驗來驗證一下,實驗的IP分配如表1-1所示。
表1-1 LVS會話實驗的服務器IP分配表

系統為CentOS 7.6 x86_64,內核版本為3.10.0-957.21.3.el7.x86_64,雙網卡,這里準備將VIP地址綁定在eth1網卡上面。
由于這里是最小化安裝,所以先安裝編譯工具等,另外為了不影響實驗結果,建議關閉iptables防火墻和SELinux,它們會直接影響實驗結果。在后端的兩臺Web服務器上直接安裝了HTTPD服務,并分別設定了它們不同的首頁地址,以示區分。
要注意的是,IPVS是LVS的關鍵,因為LVS的IP負載均衡技術就是通過IPVS模塊來實現的,IPVS是LVS集群系統的核心軟件,而IPVS具體是由ipvsadm來實現的。我們首先用如下命令查看當前內核是否支持:
lsmod | grep ip_vs
結果發現是不支持的,其解決方法呢?
這時需要在LVS-MASTER機器上安裝ipvsadm軟件,這里采用yum安裝的方式,命令如下:
yum -y install ipvsadm
安裝成功以后我們可以輸入ipvsadm命令驗證,應該有如下顯示:
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
查看ipvsadm版本,命令如下:
ipvsadm –verision
結果顯示如下:
ipvsadm v1.27 2008/5/15 (compiled with popt and IPVS v1.2.1)
我們可以看看是否有ip_vs模塊,輸入如下命令驗證:
lsmod | grep ip_vs
顯示結果如下:
ip_vs_wrr 12697 1 ip_vs 145497 3 ip_vs_wrr nf_conntrack 137239 1 ip_vs libcrc32c 12644 3 xfs,ip_vs,nf_conntrack
現在,編寫并運行init.sh腳本,綁定VIP地址到LVS-MASTER上,并設定LVS工作模式等,腳本內容如下:
#!/bin/bash VIP=192.168.100.188 RIP1=192.168.100.23 RIP2=192.168.100.24 . /etc/rc.d/init.d/functions logger $0 called with $1 case "$1" in start) echo " Start LVS of DirectorServer" #這里將VIP地址綁定在eth1網卡上 /sbin/ifconfig eth1:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev eth1:0 echo "1" >/proc/sys/net/ipv4/ip_forward #清空原先的規則表 /sbin/ipvsadm -C #重設規則表 /sbin/ipvsadm -A -t $VIP:80 -s wrr -p 150 #如果沒有-p參數的話,訪問VIP地址時會發現在后端的兩臺Web上有輪詢切換 /sbin/ipvsadm -a -t $VIP:80 -r $RIP1:80 -g /sbin/ipvsadm -a -t $VIP:80 -r $RIP2:80 -g #開始運行ipvsadm /sbin/ipvsadm ;; stop) echo "close LVS Directorserver" echo "0" >/proc/sys/net/ipv4/ip_forward /sbin/ipvsadm -C /sbin/ifconfig eth1:0 down ;; *) echo "Usage: $0 {start|stop}" exit 1 esac
給予腳本initial.sh執行權限,并執行它,命令如下:
./initial.sh start
腳本顯示結果如下:
IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.100.188:80 wrr persistent 150 -> 192.168.100.23:80 Route 1 0 0 -> 192.168.100.24:80 Route 1 0 0
ActiveConn表示活動連接數,也就是TCP連接狀態的ESTABLISHED;InActConn表示其他非活動連接數,即所有的其他狀態和TCP連接數。
最后,在后端的兩臺Web服務器上執行realserver.sh腳本,此腳本的作用為綁定VIP地址并設定ARP抑制,腳本realserver.sh的代碼如下:
#!/bin/bash VIP=192.168.100.188 . /etc/rc.d/init.d/functions case "$1" in start) ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP /sbin/route add -host $VIP dev lo:0 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 sysctl -p >/dev/null 2>&1 echo "RealServer Start OK" ;; stop) ifconfig lo:0 down route del $LVS_VIP >/dev/null 2>&1 echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce echo "RealServer Stoped" ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0
分別在兩臺Web機器上執行腳本,命令如下:
./realserver.sh start
然后我們就可以通過訪問VIP地址來訪問后端真正提供HTTP的服務器了。
LVS持久性連接的特性如下:把同一個客戶的請求信息記錄到LVS的Hash表里,保存時間使用persistence_timeout(Keepalived配置文件)控制,單位為秒。persistence_granularity參數(ipvsadm里的-M參數)是配合persistence_timeout的,在某些情況特別有用,它的值是子網掩碼,表示持久連接的粒度,默認是255.255.255.255,也就是單獨的客戶端IP,如果改成255.255.255.0就表示一個網段的都會被分配到同一臺后端Web機器上。
一個連接創建后空閑時的超時時間分為如下3類:
·TCP的空閑超時時間。
·LVS收到客戶端tcpfin的超時時間。
·UDP的超時時間。
可以用如下命令查看這些值:
ipvsadm -L --timeout
命令顯示結果如下所示:
Timeout (tcp tcpfin udp): 900 120 300
我們用ipvsadm驗證下,命令如下:
ipvsadm -Lcn
結果如下:
IPVS connection entries pro expire state source virtual destination TCP 01:51 FIN_WAIT 10.0.0.7:54914 10.0.0.18:80 10.0.0.14:80 TCP 00:35 FIN_WAIT 10.0.0.7:54866 10.0.0.18:80 10.0.0.14:80 TCP 01:51 NONE 10.0.0.7:0 10.0.0.18:80 10.0.0.14:80 TCP 01:52 FIN_WAIT 10.0.0.7:54915 10.0.0.18:80 10.0.0.14:80
如果用戶配置了持久化時間persistence_timeout,在客戶端的請求到達LB后,IPVS會在記錄表里添加一條state為NONE的連接記錄。該連接記錄的源IP為客戶端IP,端口為0,超時時間為上面所說的持久化時間persistence_timeout,會逐步減小。當NONE的超時時間減到0時,如果IPVS記錄中還存在ESTABLISHED或FIN_WAIT狀態的連接,則persistence_timeout的值會刷新為初始值。
在該NONE狀態的連接記錄存在的期間,同一客戶端IP的消息都會被調度到同一個RS節點。(NONE狀態的連接不是表示一個具體的連接,而是代表一個客戶端IP的連接模板,源端口用0表示。在IPVS上會記錄具體的連接狀態,并顯示具體的源端口)。
ESTABLISHED前面的超時時間就是tcp|tcpfin|udp中TCP的值。該值表示一條TCP連接記錄的空閑釋放時間。如果客戶端和服務端建立了連接,則IPVS中會出現一條ESTABLISHED的記錄。每當客戶端和服務端的連接中有信息交互時,該超時時間都會刷新為初始值。如果連接處于空閑狀態,即一直沒有信息交互,則等到該值超時后,ESTABLISHED的記錄會直接消失(在這種情況下IPVS記錄不會進入FIN_WAIT),實際上TCP連接還是存在的,并沒有中斷,但是由于持久化時間到了,后續同一客戶端(IP+Port)過來的請求會重新調度。所以長連接業務場景需要注意根據業務需要設置好這個TCP空閑連接的超時時間。
FIN_WAIT前面的超時時間就是tcp|tcpfin|udp中tcpfin的值。在IPVS記錄的每一條連接中,如果客戶端發起了FIN斷連,則IPVS中記錄的連接狀態會從ESTABLISHED變為FIN_WAIT。該值超時后,FIN_WAIT狀態的記錄直接消失。
還有一個細節要注意,如果用戶沒有配置持久化時間persistence_timeout,那么在ipvsadm查詢的記錄里是不會生成NONE記錄模板的,因為此時不需要持久化。但是ipvsadm記錄中還是會生成ESTABLISHED記錄的,后續同一客戶端(IP+PORT)的請求都會調度給同一個服務器,直到該連接達到了TCP空閑連接超時時間后,ESTABLISHED記錄消失,IPVS才會重新調度該客戶端的請求。這個機制是必需的,不能算作持久化(持久化針對的是同一客戶端IP,可以是不同端口)。因為TCP在傳輸的過程中可能會出現報文分片,如果IPVS把來自同一客戶端(IP+PORT)的不同分片調度給了不同的服務器,那么服務器收到報文分片后無法重新組合報文。
參考文檔如下:
http://www.linuxvirtualserver.org/docs/persistence.html
https://blog.csdn.net/yujin2010good/article/details/88732377
- Windows Vista基礎與應用精品教程
- Persistence in PHP with the Doctrine ORM
- vSphere Virtual Machine Management
- Ubuntu Linux操作系統
- Linux系統安全基礎:二進制代碼安全性分析基礎與實踐
- Application Development in iOS 7
- Mastering Reactive JavaScript
- Windows 7實戰從入門到精通
- 從零開始學安裝與重裝系統
- Advanced Infrastructure Penetration Testing
- Linux應用大全 基礎與管理
- Azure Resource Manager Templates Quick Start Guide
- Linux深度攻略
- Docker for Developers
- 從零開始學Windows 7