预计阅读本页时间:-
7.3.1 LVS的会话保持机制
LVS是利用配置文件里的persistence(单位为秒)设置来设定会话保持时间的,这个选项对于电子商务网站来说尤其有用:当用户从远程用账号登录网站时,有了这个会话保持功能,就能把用户的请求转发给同一个应用服务器了。在这里我们来做一个假设,假定现在有一个LVS环境,使用VS/DR转发模式,真实的Web服务器有2个,假设LVS负载均衡器不启用会话保持功能。当用户第一次访问的时候,他的访问请求被负载均衡器转给某个真实的服务器,这样他看到一个登录页面,第一次访问完毕;接着他在登录框里填写用户名和密码,然后提交;这时候,问题可能就会出现了——登录不成功。因为没有会话保持,负载均衡器可能会把第2次的请求转发到其他的服务器上,这样浏览器又会提醒客户需要再次输入用户名及密码。
在这里可以做一个简单的实验来验证一下,实验的IP分配如表7-1所示。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
表7-1 LVS会话实验的服务器IP分配表
这里的系统为CentOS 6.4 x86_64,内核版本为2.6.32-573.12.1.el6.x86_64。
由于笔者之前使用的是最小化安装,所以要先安装下编译工具等,另外为了不影响实验结果,建议关闭iptables防火墙和SELinux,它们会直接影响实验结果;在后端的两台Web服务器上笔者直接安装了httpd服务,并分别设定了不同的首页地址,以示区分,安装基础的编译工具和ipvsadm软件需要的基础软件包的命令如下:
yum -y install gcc gcc-c++ kernel-devel libnl* libpopt* popt-static
其中,IPVS是LVS的关键,因为LVS的IP负载均衡技术就是通过IPVS模块来实现的,IPVS是LVS集群系统的核心软件,而IPVS具体是由ipvsadm来实现的。下面首先用命令查看下当前内核是否支持IPVS,命令如下所示:
lsmod |?grep ip_vs
结果发现是不支持的。
那么,需要在LVS-MASTER机器上安装ipvsadm软件,这里采用源码安装的方式,命令如下所示:
mkdir -p /usr/local/src
cd /usr/local/src
wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz
tar xvf ipvsadm-1.26.tar.gz
cd ipvsadm-1.26
ln -s /usr/src/kernels/2.6.32-573.12.1.el6.x86_64/ /usr/src/linux
make
make install
安装成功以后输入ipvsadm命令验证,应该有如下显示:
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
要确定是否有ip_vs模块,可输入如下命令验证:
lsmod | grep ip_vs
显示结果如下所示:
ip_vs 115643 0
libcrc32c 1246 1 ip_vs
ipv6 321422 16 ip_vs,ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6
上面的结果表示ip_vs模块已成功加载,然后编写并运行lvs-initialization.sh脚本,其作用为绑定VIP地址到LVS-MASTER上,并且设定LVS工作模式等,脚本内容如下所示:
#!/bin/bash
VIP=192.168.1.210
RIP1=192.168.1.205
RIP2=192.168.1.206
. /etc/rc.d/init.d/functions
logger $0 called with $1
case "$1" in
start)
echo " Start LVS of DirectorServer"
/sbin/ifconfig eth0:0 $VIP broadcast $VIP netmask 255.255.255.255 up
/sbin/route add -host $VIP dev eth0:0
echo "1" >/proc/sys/net/ipv4/ip_forward
#Clear ipvsadm table
/sbin/ipvsadm -C
#Set LVS rules
/sbin/ipvsadm -A -t $VIP:80 -s wrr -p 120
#如果没有
-p参数的话,我们后续访问
VIP地址时会发现,
VIP地址会在后端的两台
Web机器上轮询切换
/sbin/ipvsadm -a -t $VIP:80 -r $RIP1:80 -g
/sbin/ipvsadm -a -t $VIP:80 -r $RIP2:80 -g
#Run LVS
/sbin/ipvsadm
;;
stop)
echo "close LVS Directorserver"
echo "0" >/proc/sys/net/ipv4/ip_forward
/sbin/ipvsadm -C
/sbin/ifconfig eth0:0 down
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
为脚本lvs-initialization.sh执行权限,并执行它,命令如下所示:
./lvs-initialization.sh start
脚本显示结果如下所示:
start LVS of DirectorServer
SIOCADDRT: File exists
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.210:http rr persistent 120
-> 192.168.1.205:http Route 1 0 0
-> 192.168.1.206:http Route 1 0 0
ActiveConn表示活动连接数,即TCP连接状态的ESTABLISHED;InActConn表示其他非活动连接数,即所有的其他状态和TCP连接数。
最后,在后端的两台Web服务器上执行realserver.sh脚本,此脚本起的作用为:绑定VIP地址并设定ARP抑制。脚本realserver.sh的代码如下:
#!/bin/bash
SNS_VIP=192.168.1.210
. /etc/rc.d/init.d/functions
case "$1" in
start)
ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP
/sbin/route add -host $SNS_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
此脚本执行以后,就可以分别在两台Web机器上绑定VIP地址并设定ARP抑制了。
好了,现在来看看LVS持久连接技术,LVS的持久性连接涉及两个方面(分别是保存时间和空闲超时时间):
把同一个Client客户端的请求信息记录到LVS的哈希表里,保存时间使用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
显示结果分别对应了上面的3种情况。
我们用ipvsadm命令显示内核虚拟服务器表,命令如下所示:
ipvsadm -Lcn
显示结果如下所示:
IPVS connection entries
pro expire state source virtual destination
TCP 01:30 FIN_WAIT 192.168.1.222:54446 192.168.1.210:80 192.168.1.206:80
TCP 01:39 NONE 192.168.1.222:0 192.168.1.210:80 192.168.1.206:80
TCP 01:39 FIN_WAIT 192.168.1.222:54500 192.168.1.210:80 192.168.1.206:80
TCP 01:32 FIN_WAIT 192.168.1.222:54460 192.168.1.210:80 192.168.1.206:80
TCP 01:39 FIN_WAIT 192.168.1.222:54488 192.168.1.210:80 192.168.1.206:80
当任意一个客户端访问LVS的VIP地址时,IPVS都会记录一条状态为NONE的信息,expire初始值是persistence_timeout的值,然后根据时钟主键变小,在以下记录存在期间,同一客户端IP连接上来后,都会被分配到同一个后端。
FIN_WAIT的值就是tcpfin的超时时间,当NONE的值为0时,如果FIN_WAIT还存在,那么NONE的值会重新变成60秒,然后再减少,直到FIN_WAIT消失,NONE才会消失,只要NONE存在,同一客户端的访问都会分配到统一的Real Server上面。这个说法很好验证,大家只要不停地执行ipvsadm-Lcn的命令,观察其时间变化即可。
参考文档和资料:
http://www.linuxvirtualserver.org/docs/persistence.html 。
http://xstarcd.github.io/wiki/sysadmin/lvs_persistence.html 。