LVS/Nginx如何处理session问题
<转自http://blog.wqgcool.com/?p=634>
业务系统架构为:
拓补一:Nginx(master)+keepalived+Nginx(backup)+3台web集群+mysql(master-slave)+EMC CLARiiON CX4存储拓补二:lvs(master)+keepalived+lvs(backup) +3台web集群+mysql(master-slave)+EMC CLARiiON CX4存储
操作系统用的是64位RHEl5.4/Centos5.4,服务器采用HP360G6+HP580G5,业务系统最前端的防火墙为华赛USG5000+WAF-T3-500(防DDOS、钓鱼式及注入式攻击等)
拓补一中,如采用Nginx负载均衡器,采用的ip_hash来代替默认的rr方式,即可以将某客户端IP的请求通过哈希算法定位到同一台后端 web服务器上,这样避免了session丢失,解决了session问题。但ip_hash指令无法保证后端服务器的负载均衡,可能有些后端服务器接收的请求多,有些后端服务器接收的请求少;这样失去了负载均衡的意义。我们的解决方案是将用户的登录session信息写进后端的Mysql数据库,这个在后面的CMS系统中也实现了,效果也不错;后来我提出了折衷方案,如果Nginx并发连接数(即Nginx负载均衡器的NginxStatus的 active connections)>2000,即采用将session写进MySQL数据库的方法;如果并发数小的话,ip_hash效果也是相当好的。
另外,如果在upstream中添加了ip_hash参数后,经测试发现后台的某台服务器挂掉后不会自动跳转,可建议采用如下写法:
1. upstream njzq.com {
2.ip_hash;
3.server172.16.94.216:9000max_fails=0;
4.server172.16.94.217:9000max_fails=0;
5.server172.16.94.218:9000max_fails=0;
6. }拓补二中,lvs采用的ipvsadm -p方案,persistence-会话保持时间,单位是秒。我一般是设为120s,这个选项对动态网站很有用处:当用户从远程用帐号进行登陆网站时,有了这个会话保持功能,就能把用户的请求转发给同一个应用服务器。当用户第一次访问的时候,他的访问请求被负载均衡器转给某个真实服务器,这样他看到一个登陆页面,第一次访问完毕;接着他在登陆框填写用户名和密码,然后提交;这时候,问题就可能出现了—登陆不能成功。因为没有会话保持,负载均衡器可能会把第 2次的请求转发到其他的服务器。那么设置后是不是前面的客户机跟后面的服务器都永远建议连接关系呢,蛮或是过了120秒后或切换到另一台真实的物理服务器呢?我尝试作了以下实验,lvs采用单台,192.168.1.102,VIP为192.168.1.188,后端为二台web服务器,192.168.1.103和192.168.1.104。
lvs上面执行下列脚本,二台真实的服务器下也要执行相关脚本,绑定vip地址192.168.1.188;lvs和真实物理服务器上分别使用lvs_dr.sh和real.sh脚本
1. [root@ltos lvs]# cat lvs_dr.sh
2.#!/bin/bash
3.
4.#websitedirectorvip.
5.SNS_VIP=192.168.1.188
6.SNS_RIP1=192.168.1.103
7.SNS_RIP2=192.168.1.104
8.
9../etc/rc.d/init.d/functions
10.
11.logger$0calledwith$1
12.
13.case“$1″in
14.
15.start)
16.#setsquidvip
17./sbin/ipvsadm–set30560
18./sbin/ifconfigeth0:0$SNS_VIPbroadcast$SNS_VIPnetmask255.255.255.255broadcast$SNS_VIPup
19./sbin/routeadd-host$SNS_VIPdeveth0:0
20./sbin/ipvsadm-A-t$SNS_VIP:80-swlc-p120
21./sbin/ipvsadm-a-t$SNS_VIP:80-r$SNS_RIP1:80-g-w1
22./sbin/ipvsadm-a-t$SNS_VIP:80-r$SNS_RIP2:80-g-w1
23.touch/var/lock/subsys/ipvsadm>/dev/null2>&1
24.
25.;;
26.stop)
27./sbin/ipvsadm-C
28./sbin/ipvsadm-Z
29.ifconfigeth0:0down
30.routedel$SNS_VIP
31.rm-rf/var/lock/subsys/ipvsadm>/dev/null2>&1
32.echo“ipvsadmstoped”
33.;;
34.
35.status)
36.
37.if[!-e/var/lock/subsys/ipvsadm];then
38.echo“ipvsadmstoped”
39.exit1
40.else
41.echo“ipvsadmOK”
42.fi
43.;;
44.
45.*)
46.echo“Usage:$0{start|stop|status}”
47.exit1
48.esac
49. exit 0二台web真实物理服务器运行real.sh脚本
1. #!/bin/bash
2.SNS_VIP=192.168.1.188
3../etc/rc.d/init.d/functions
4.
5.case“$1″in
6.start)
7.ifconfiglo:0$SNS_VIPnetmask255.255.255.255broadcast$SNS_VIP
8./sbin/routeadd-host$SNS_VIPdevlo:0
9.echo“1″>/proc/sys/net/ipv4/conf/lo/arp_ignore
10.echo“2″>/proc/sys/net/ipv4/conf/lo/arp_announce
11.echo“1″>/proc/sys/net/ipv4/conf/all/arp_ignore
12.echo“2″>/proc/sys/net/ipv4/conf/all/arp_announce
13.sysctl-p>/dev/null2>&1
14.echo“RealServerStartOK”
15.;;
16.stop)
17.ifconfiglo:0down
18.routedel$SNS_VIP>/dev/null2>&1
19.echo“0″>/proc/sys/net/ipv4/conf/lo/arp_ignore
20.echo“0″>/proc/sys/net/ipv4/conf/lo/arp_announce
21.echo“0″>/proc/sys/net/ipv4/conf/all/arp_ignore
22.echo“0″>/proc/sys/net/ipv4/conf/all/arp_announce
23.echo“RealServerStoped”
24.;;
25.*)
26.echo“Usage:$0{start|stop}”
27.exit1
28.esac
29. exit 0通过观察得知,当 客户机192.168.1.100发起第一次连接请求时,lvs负载均衡器将其分配到后面的真实物理服务器192.168.1.104,在完成了三次握手后,连接的状态为ESTABLISHED,随后在终止TCP连接的相当一段时间内,真实web服务器的状态为FIN_WAIT,而在此段时间 192.168.1.100发起的新连接,会一直连接到192.168.1.104。