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. server 172.16.94.216:9000 max_fails=0;
4. server 172.16.94.217:9000 max_fails=0;
5. server 172.16.94.218:9000 max_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. # website director vip.
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 $0 called with $1
12.
13. case “$1″ in
14.
15. start)
16. # set squid vip
17. /sbin/ipvsadm –set 30 5 60
18. /sbin/ifconfig eth0:0 $SNS_VIP broadcast $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP up
19. /sbin/route add -host $SNS_VIP dev eth0:0
20. /sbin/ipvsadm -A -t $SNS_VIP:80 -s wlc -p 120
21. /sbin/ipvsadm -a -t $SNS_VIP:80 -r $SNS_RIP1:80 -g -w 1
22. /sbin/ipvsadm -a -t $SNS_VIP:80 -r $SNS_RIP2:80 -g -w 1
23. touch /var/lock/subsys/ipvsadm >/dev/null 2>&1
24.
25. ;;
26. stop)
27. /sbin/ipvsadm -C
28. /sbin/ipvsadm -Z
29. ifconfig eth0:0 down
30. route del $SNS_VIP
31. rm -rf /var/lock/subsys/ipvsadm >/dev/null 2>&1
32. echo “ipvsadm stoped”
33. ;;
34.
35. status)
36.
37. if [ ! -e /var/lock/subsys/ipvsadm ];then
38. echo “ipvsadm stoped”
39. exit 1
40. else
41. echo “ipvsadm OK”
42. fi
43. ;;
44.
45. *)
46. echo “Usage: $0 {start|stop|status}”
47. exit 1
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. ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP
8. /sbin/route add -host $SNS_VIP dev lo: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/null 2>&1
14. echo “RealServer Start OK”
15. ;;
16. stop)
17. ifconfig lo:0 down
18. route del $SNS_VIP >/dev/null 2>&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 “RealServer Stoped”
24. ;;
25. *)
26. echo “Usage: $0 {start|stop}”
27. exit 1
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。

猜你喜欢

转载自yypiao.iteye.com/blog/1169457