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 。