官术网_书友最值得收藏!

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

主站蜘蛛池模板: 阆中市| 邵阳县| 综艺| 沙雅县| 潜山县| 广元市| 辉县市| 阳江市| 泽普县| 邮箱| 平谷区| 芷江| 阳曲县| 延边| 丘北县| 湘乡市| 惠州市| 桐柏县| 分宜县| 天长市| 沁源县| 华坪县| 台中市| 灵山县| 红安县| 宜兰市| 高台县| 沙洋县| 喀喇沁旗| 邻水| 巴林左旗| 布尔津县| 化州市| 沁水县| 铅山县| 迁西县| 鄢陵县| 疏附县| 东台市| 仁化县| 霍城县|