标签:lvs

LVS负载均衡之session解决方案 持久连接

No Comments Linux

原文地址:http://minux.blog.51cto.com/8994862/1744761<br><br>1. 持久连接是什么?

1.1 在LVS中,持久连接是为了用来保证当来自同一个用户的请求时能够定位到同一台服务器。

2. 为什么会用到持久连接?

2.1 cookie/session机制的简单说明:

在Web服务通信中,HTTP本身是无状态协议,不能标识用户来源,此时出现了一个问题,当用户在一个网站浏览了A网页并跳转到B网页,此时服务器就认为B网页是一个新的用户请求,你之前的登陆的信息就都丢失了,头疼。为了记录用户的会话信息,我们的开发者就在客户端/服务器端软件提供了cookie/session机制,当你访问网站时,服务器端建立一个session会话区,并建立一个cookie与这个session绑定,将信息发送给你的浏览器。这样,只要你的cookie存在,服务器端的session存在,那么当你打开新页面的时候,服务器依然会认识你!

2.2 cookie/session由负载均衡导致的问题:

上面说服务器需要靠session/cookie来标记用户的会话,这没什么问题。不过,当你在做了负载均衡的时候,就出现了问题。

我们依然假设一个场景:某电商网站为了实现更多用户的访问,提供了A、B两台服务器,并在前面做了LVS负载均衡。于是某用户打开了某购物网站,选中了一件衣服,并加入了购物车(此时背后的操作是:LVS负载均衡器接受了用户请求,并将其分发到了选中的服务器,并将用户添加了一件衣服记录到这个会话的session中)。这时当用户打开了第二个网页,又选中了一件帽子并加入购物车(此时背后的操作是:LVS负载均衡器接受了用户请求,进行计算,将其发送到选中的服务器上,该服务器将用户添加了一件帽子记录到session中)。

到现在可能各位已经发现问题了,由于LVS是一个四层负载均衡器,仅能根据IP:Port对数据报文进行分发,不能确保将同一用户根据session发往同一个服务器,也就是用户第一次被分配到了A服务器,而第二次可能分配到了B服务器,但是B服务器并没有A服务器用户的session记录,直接导致这个例子里的用户发现自己的购物车没有了之前的衣服,而仅有帽子。这是不可接受的。

为了避免上面的问题,生产环境中一般有三种方案:

2.2.1 将来自于同一个用户的请求发往同一个服务器

2.2.2 将session信息在服务器集群内共享,每个服务器都保存整个集群的session信息

2.2.3 建立一个session存储池,所有session信息都保存到存储池中

显然,第一种方案是最简单,也是最节约资源的,而持久连接和sh算法就是实现第一种方案的两种方式。由于sh的应用并不是太多,我们仅仅介绍一下其和持久连接的区别,其他的就不讲述了,有兴趣的朋友可以自行查找资料。

3. LVS的sh算法和持久连接:

sh算法全称为source hash(源地址hash),它和持久连接的作用都是"将来自同一个IP的请求都转发到同一个Server",从而保证了session会话定位的问题。两者的不同是:

(1)sh算法:使用SH算法,SH算法在内核中会自动维护一个哈希表,此哈希表中用每一个请求的源IP地址经过哈希计算得出的值作为键,把请求所到达的RS的地址作为值。在后面的请求中,每一个请求会先经过此哈希表,如果请求在此哈希表中有键值,那么直接定向至特定RS,如没有,则会新生成一个键值,以便后续请求的定向。但是此种方法在时间的记录上比较模糊(依据TCP的连接时长计算),而且其是算法本身,所以无法与算法分离,并不是特别理想的方法。

(2)持久连接:此种方法实现了无论使用哪一种调度方法,持久连接功能都能保证在指定时间范围之内,来自于同一个IP的请求将始终被定向至同一个RS,还可以把多种服务绑定后统一进行调度。

详细一点说:当用户请求到达director时。无论使用什么调度方法,都可以实现对同一个服务的请求在指定时间范围内始终定向为同一个RS。在director内有一个LVS持久连接模板,模板中记录了每一个请求的来源、调度至的RS、维护时长等等,所以,在新的请求进入时,首先在此模板中检查是否有记录(有内置的时间限制,比如限制是300秒,当在到达300秒时依然有用户访问,那么持久连接模板就会将时间增加两分钟,再计数,依次类推,每次只延长2分钟),如果该记录未超时,则使用该记录所指向的RS,如果是超时记录或者是新请求,则会根据调度算法先调度至特定RS,再将调度的记录添加至此表中。这并不与SH算法冲突,lvs持久连接会在新请求达到时,检查后端RS的负载状况,这就是比较精细的调度和会话保持方法。

4. LVS的三种持久连接方式:

------中间广告---------

(1)PCC:每客户端持久;将来自于同一个客户端的所有请求统统定向至此前选定的RS;也就是只要IP相同,分配的服务器始终相同。

(2)PPC:每端口持久;将来自于同一个客户端对同一个服务(端口)的请求,始终定向至此前选定的RS。例如:来自同一个IP的用户第一次访问集群的80端口分配到A服务器,25号端口分配到B服务器。当之后这个用户继续访问80端口仍然分配到A服务器,25号端口仍然分配到B服务器。

(3)PFMC:持久防火墙标记连接;将来自于同一客户端对指定服务(端口)的请求,始终定向至此选定的RS;不过它可以将两个毫不相干的端口定义为一个集群服务,例如:合并http的80端口和https的443端口定义为同一个集群服务,当用户第一次访问80端口分配到A服务器,第二次访问443端口时仍然分配到A服务器。

5.定义LVS持久连接:

LVS的持久连接功能需要定义在集群服务上面,使用-p timeout选项。

5.1 定义PPC:

1

[root@localhost ~]# ipvsadm -At 172.16.10.1:80 -s rr -p 300

上面命令的意思是:添加一个集群服务为172.16.10.1:80,使用的调度算法为rr,持久连接的保持时间是300秒。当超过300秒都没有请求时,则清空LVS的持久连接模板。

5.2 定义PCC:

[root@localhost ~]# ipvsadm -A -t 192.168.1.200:0 -s rr -p 600

[root@localhost ~]# ipvsadm -a -t 192.168.1.200:0 -r 192.168.1.10 -g -w 2

[root@localhost ~]# ipvsadm -a -t 192.168.1.200:0 -r 192.168.1.20 -g -w 1

5.3 定义PFMC:

######PNMPP是通过路由前给数据包打标记来实现的

[root@localhost ~]# iptables -t mangle -A PREROUTING -d 192.168.1.200 -eth0 -p tcp --dport 80 -j MARK --set-mark 3

[root@localhost ~]# iptables -t mangle -A PREROUTING -d 192.168.1.200 -eth0 -p tcp --dport 443 -j MARK --set-mark 3

[root@localhost ~]# ipvsadm -A -f 3 -s rr -p 600

[root@localhost ~]# ipvsadm -a -f 3 -r 192.168.1.10 -g -w 2

[root@localhost ~]# ipvsadm -a -f 3 -r 192.168.1.20 -g -w 2

vls dr nat 配置及测试

No Comments Linux

 

————-1.DR模式配置及测试————————————–
地址分配
DR  ens33 192.168.142.188 VIP ens33:0 192.168.142.189
RS1 192.168.142.138  VIP lo:0 192.168.142.189
RS2 192.168.142.139  VIP lo:0 192.168.142.189

 

在DR上配置

vim /opt/script/lvs_dr.sh

#! /bin/bash
#开启IP转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward   
ipvjeff=/sbin/ipvsadm
vip=192.168.142.189
rs1=192.168.142.138
rs2=192.168.142.139
#增加子接口
ifconfig ens33:0 down
ifconfig ens33:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev ens33:0
#清空原有lvs配置
$ipvjeff -C
#定义一个集群服务 RR算法
$ipvjeff -A -t $vip:80 -s rr
#添加一个后端服务器 模式为dr
$ipvjeff -a -t $vip:80 -r $rs1:80 -g
$ipvjeff -a -t $vip:80 -r $rs2:80 -g

chmod +x /opt/script/lvs_dr.sh
脚本需要开机运行
[root@lvs-d script]# ./lvs_dr.sh
SIOCSIFFLAGS: Cannot assign requested address
SIOCADDRT: No such device
[root@lvs-d script]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@lvs-d script]# ./lvs_dr.sh
SIOCADDRT: No such device

配置real server 服务
后端所有应用服务器都需要配置
#vim /opt/script/rs.sh
#! /bin/bash
vip=192.168.142.189
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip 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
脚本需要开机运行
chmod +x /opt/script/rs.sh

运行脚本
[root@mysql02 script]# ip a  |grep 192
    inet 192.168.142.189/32 brd 192.168.142.189 scope global lo:0—验证
    inet 192.168.142.139/24 brd 192.168.142.255 scope global ens33

永久保存LVS规则并恢复
[root@LVS ~]# ipvsadm -S > /etc/sysconfig/ipvsadm.s1
模拟清空ipvsadm规则来恢复
[root@LVS ~]# ipvsadm -C
[root@LVS ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
[root@lvs-d script]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.142.188:80 wrr
  -> 10.1.1.11:80                 Masq    2      0          0        
  -> 10.1.1.12:80                 Masq    1      0          0        
[root@lvs-d script]#

——–SIOCADDRT:No Such Device—–
dev 后指定设备 必须是已经存在的网卡设备
检查配置接口是否配置正确

验证
#查看ipvs定义的规则列表
[root@lvs-d script]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.142.189:80 rr
  -> 192.168.142.138:80           Route   1      2          2        
  -> 192.168.142.139:80           Route   1      2          1        
[root@lvs-d script]#

 

[root@lvs-d script]# ip a |grep 192
    inet 192.168.142.188/24 brd 192.168.142.255 scope global ens33
    inet 192.168.142.189/32 brd 192.168.142.189 scope global ens33:0

[root@lvs-d script]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    100    0        0 ens33
192.168.142.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33
lvs-d           0.0.0.0         255.255.255.255 UH    0      0        0 ens33 —-这个必须有
[root@lvs-d script]#

[root@lvs-d script]# vim lvs_dr.sh
[root@lvs-d script]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.142.188  netmask 255.255.255.0  broadcast 192.168.142.255
        inet6 fe80::20c:29ff:febd:8934  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:bd:89:34  txqueuelen 1000  (Ethernet)
        RX packets 7422  bytes 7825737 (7.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3109  bytes 294100 (287.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.142.189  netmask 255.255.255.255  broadcast 192.168.142.189
        ether 00:0c:29:bd:89:34  txqueuelen 1000  (Ethernet)

       
进行web验证—-curl

RR算法 每次会进行轮换,出下列效果为正常

jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$

[root@lvs-d script]# ipvsadm -L -n –stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  192.168.142.189:80                 77      491        0    46381        0
  -> 192.168.142.138:80                 38      220        0    14254        0
  -> 192.168.142.139:80                 39      271        0    32127        0
[root@lvs-d script]#

————-2.nat模式配置及测试————————————–
优势很明显,配置简单
DR  ens33 192.168.142.188
    vlan 10 : 10.1.1.188
RS1 vlan 10 :10.1.1.11 GW10.1.1.188 切记:关闭本地ens33接口,只留10.1.1.11接口
RS2 vlan 10 :10.1.1.12 GW10.1.1.188 切记:关闭本地ens33接口,只留10.1.1.12接口
接口使用vlan 10或 网络连接方式:Host-Only

dr上运行如下脚本
vim /opt/script/lvs_nat.sh

#! /bin/bash
#开启IP转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvjeff=/sbin/ipvsadm
vip=192.168.142.188
rs1=10.1.1.11
rs2=10.1.1.12
#清空原有lvs配置
$ipvjeff -C
#定义一个集群服务 RR算法
$ipvjeff -A -t $vip:80 -s wrr
#添加一个后端服务器 模式为dr
$ipvjeff -a -t $vip:80 -r $rs1 -m -w 2
$ipvjeff -a -t $vip:80 -r $rs2 -m -w 1

chmod +x /opt/script/lvs_nat.sh
脚本需要开机运行
[root@lvs-d script]# ./lvs_nat.sh
SIOCSIFFLAGS: Cannot assign requested address
SIOCADDRT: No such device
[root@lvs-d script]# echo 1 > /proc/sys/net/ipv4/ip_forward

永久保存LVS规则并恢复
[root@LVS ~]# ipvsadm -S > /etc/sysconfig/ipvsadm.s1
模拟清空ipvsadm规则来恢复
[root@LVS ~]# ipvsadm -C
[root@LVS ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
[root@lvs-d script]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.142.188:80 wrr
  -> 10.1.1.11:80                 Masq    2      0          0        
  -> 10.1.1.12:80                 Masq    1      0          0        
[root@lvs-d script]#

配置real server 服务
后端所有应用服务器都需要配置
只需配置IP其余不用配置

测试 和权重一致即为正确
jeff@ubuntu:~$ curl http://192.168.142.188
r1
jeff@ubuntu:~$ curl http://192.168.142.188
r1
jeff@ubuntu:~$ curl http://192.168.142.188
r2
jeff@ubuntu:~$
                                      

——–SIOCADDRT:No Such Device—–
dev 后指定设备 必须是已经存在的网卡设备
检查配置接口是否配置正确

验证
#查看ipvs定义的规则列表
[root@lvs-d script]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.142.189:80 rr
  -> 192.168.142.138:80           Route   1      2          2        
  -> 192.168.142.139:80           Route   1      2          1        
[root@lvs-d script]#

 

[root@lvs-d script]# ip a |grep 192
    inet 192.168.142.188/24 brd 192.168.142.255 scope global ens33
    inet 192.168.142.189/32 brd 192.168.142.189 scope global ens33:0

[root@lvs-d script]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    100    0        0 ens33
192.168.142.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33
lvs-d           0.0.0.0         255.255.255.255 UH    0      0        0 ens33 —-这个必须有
[root@lvs-d script]#

[root@lvs-d script]# vim lvs_dr.sh
[root@lvs-d script]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.142.188  netmask 255.255.255.0  broadcast 192.168.142.255
        inet6 fe80::20c:29ff:febd:8934  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:bd:89:34  txqueuelen 1000  (Ethernet)
        RX packets 7422  bytes 7825737 (7.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3109  bytes 294100 (287.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.142.189  netmask 255.255.255.255  broadcast 192.168.142.189
        ether 00:0c:29:bd:89:34  txqueuelen 1000  (Ethernet)

       
进行web验证—-curl

RR算法 每次会进行轮换,出下列效果为正常

jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl
http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$ curl http://192.168.142.189
r1
jeff@ubuntu:~$ curl http://192.168.142.189
r2
jeff@ubuntu:~$

[root@lvs-d script]# ipvsadm -L -n –stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  192.168.142.189:80                 77      491        0    46381        0
  -> 192.168.142.138:80                 38      220        0    14254        0
  -> 192.168.142.139:80                 39      271        0    32127        0
[root@lvs-d script]#
       
       
—————–ipvsadm组件定义规则的格式:
1.定义集群服务格式:
(1).添加集群服务:
ipvsadm -A|E -t|u|f service-address [-s scheduler]
              [-p [timeout]] [-M netmask]
-A:                  表示添加一个新的集群服务
-E:                  编辑一个集群服务
-t:                  表示tcp协议
-u:                  表示udp协议
-f:                  表示firewall-Mark,防火墙标记
service-address:     集群服务的IP地址,即VIP
-s                    指定调度算法
-p                    持久连接时长,如#ipvsadm -Lcn ,查看持久连接状态
-M                    定义掩码
ipvsadm -D -t|u|f service-address      删除一个集群服务
ipvsadm -C                             清空所有的规则
ipvsadm -R                             重新载入规则
ipvsadm -S [-n]                        保存规则
2.向集群服务添加RealServer规则:
(1).添加RealServer规则
ipvsadm -a|e -t|u|f service-address -r server-address
              [-g|i|m] [-w weight]
-a                 添加一个新的realserver规则
-e                 编辑realserver规则
-t                 tcp协议
-u                 udp协议
-f                 firewall-Mark,防火墙标记
service-address    realserver的IP地址
-g                 表示定义为LVS-DR模型
-i                 表示定义为LVS-TUN模型
-m                 表示定义为LVS-NAT模型
-w                 定义权重,后面跟具体的权值
ipvsadm -d -t|u|f service-address -r server-address          –删除一个realserver
ipvsadm -L|l [options]                                       –查看定义的规则
如:#ipvsadm -L -n 
ipvsadm -Z [-t|u|f service-address]                          –清空计数器
清空和查看:
ipvsadm -C
ipvsadm -L|l [options]   
-n: numeric,基于数字格式显示地址和端口;
-c: connection,显示ipvs连接;
–stats:统计数据
–rate: 速率
–exact: 精确值
四、lvs的10种调度算法
可以分为两大类
LVS Scheduling Method LVS的调度方法:
1.Fixed Scheduling Method  静态调服方法
(1).RR     轮询
(2).WRR    加权轮询
(3).DH     目标地址hash
(4).SH     源地址hash
2.Dynamic Scheduling Method 动态调服方法
(1).LC     最少连接
(2).WLC    加权最少连接
(3).SED    最少期望延迟
(4).NQ     从不排队调度方法
(5).LBLC   基于本地的最少连接
(6).LBLCR  带复制的基于本地的最少连接

arp_ignore:定义接受到ARP请求时的相应级别
0:只要本地配置的有相应地址,就给予响应。
1:从这个接口进来的,并且目标地址是此接口,才给予响应
2:只回答目标IP地址是来访网络接口本地地址的ARP查询请求,且来访IP必须在该网络接口的子网段内
3:不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应
4-7:保留未使用
8:不回应所有(本地地址)的arp查询  
此处因该将arp_ignore设置为1 
 
arp_announce:定义将自己地址向外通告是的通告级别;
0: 将本地任何接口上的任何地址向外通告
1:仅响应目标网络通告与其网络匹配的地址
2:仅向与本地接口上地址匹配的网络进行通告
此处应该将arp_announce设置为2

参考
http://leeyan.blog.51cto.com/8379003/1701931/
http://wuhf2015.blog.51cto.com/8213008/1654648