persistent
persistent:持久连接
以下演示都是基于这张拓扑图:
在LVS上三种方法可实现持久连接:
- 每端口持久,通过端口映射,结合sh(源IP地址HASH算法)最常见办法
- 每防火墙标识持久,通过iptables在数据包上打mark
- 每客户端持久,基于0端口定义集群服务,即将客户端对所有应用的请求统统调度至后端主机,必须定义为持久模式;
第一种方式:每端口持久,注意要结合sh算法才能实现
[root@lvs ~]# ipvsadm -A -t 192.168.80.99:80 -s sh
[root@lvs ~]# ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.11 -g
[root@lvs ~]# ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.12 -g
[root@lvs ~]# ipvsadm -Ln
TCP 192.168.80.99:80 sh
-> 192.168.80.11:80 Route 1 0 0
-> 192.168.80.12:80 Route 1 0 0
第三种方式:通过防火墙标识持久,关于这个我专门有一篇博文,这里不过多阐述。
[root@lvs ~]# iptables -t mangle -A PREROUTING -d 192.168.80.99/32 -p tcp -m multiport --ports 80,443 -j MARK --set-mark 3
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -A -f 3 -s rr
[root@lvs ~]# ipvsadm -a -f 3 -r 192.168.80.11:80 -g
[root@lvs ~]# ipvsadm -a -f 3 -r 192.168.80.12:80 -g
[root@lvs ~]# ipvsadm -Ln
FWM 3 rr
-> 192.168.80.11:80 Route 1 0 0
-> 192.168.80.12:80 Route 1 0 0
第三种方式:每客户端持久
[root@lvs ~]# ipvsadm -A -t 192.168.80.99:80 -s rr -p
[root@lvs ~]# ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.11 -g
[root@lvs ~]# ipvsadm -a -t 192.168.80.99:80 -r 192.168.80.12 -g
[root@lvs ~]# ipvsadm -Ln
TCP 192.168.80.99:80 rr persistent 360
-> 192.168.80.11:80 Route 1 0 0
-> 192.168.80.12:80 Route 1 0 0
仔细观察上面的配置,发现第一条命令后一个-p
,意为持久连接之意,但是我们下面又是用的rr算法,这岂不是冲突了吗?如果使用了上面的配置,当用户访问的时候只有第一次是rr算法(轮询),而以后rr算法都不再生效,-p会生效,也就说当一个用户第一次访问时LVS替用户选定了一个R-SERVER,那以后用户再进来时都由同一台R-SERVER服务,rr算法失效,持久连接在算法之前生效,而且持久连接保持长达360秒。
[root@lvs ~]# ipvsadm -A -t 192.168.80.99 -s rr -p
[root@lvs ~]# ipvsadm -a -t 192.168.80.99 -r 192.168.80.12 -g
[root@lvs ~]# ipvsadm -a -t 192.168.80.99 -r 192.168.80.11 -g
[root@lvs ~]# ipvsadm -Ln
TCP 192.168.80.99:0 rr persistent 360
-> 192.168.80.11:0 Route 1 0 0
-> 192.168.80.12:0 Route 1 0 0
基于0端口定义集群服务,0代表全部端口,即将客户端对所有应用的请求统统调度至后端主机,必须定义为持久模式;
ldirectord
健康检测原理
健康检测有三种类型:
(a) 网络层检测,能ping通就认为对方在线,粗糙,能ping通但服务挂了也不成呀!
(b) 传输层检测,端口探测,端口处于侦听状态就认为对方在线,也是粗糙,万一是别人服务侦听的端口呢?
(c) 应用层检测,请求某关键资源;请求某个页面,要求返回的页面包括某个字符串就认为对方在线,这个还可以,我们下面用的ldirectord就是这种,当然也可以实现前两种。
应用场景
LVS支持的算法有一个很大的缺点,就是它只会根据本身的算法和服务器的负载进行分发,全然不顾R-SERVER是否存活,LVS本身并没有健康检测的功能,当某一个R-SERVER宕机了LVS并不会检测到,当然也就不能从规则当中踢出R-SERVER对应的IPVS规则了。
最常见的解决方案有两种:
- keepalived
- ldirectord
第一种方案:keepalived
keepalived我们会拿出专门的博文来重点阐述的,这里不过多说明,其实keepalived最大的作用就是利用数据通信领域当中VRRP协议进行冗余,通常配合LVS,实现前端负载均衡的冗余,防止负载均衡器的单点故障。其实keepalived的作用并不仅仅只有这一项,keepalived还能实现对后端R-SERVER的健康检测功能,如果R-SERVER出现了问题无法被客户端正常访问时,keepalived会及时检测到故障R-SERVER,并不会将客户端的数据发送到出问题的R-SERVER上。这是最常见的方案,一举两得。
第二种方案: ldirectord
我们刚才说过keepalived的两种功能,冗余LVS和健康检测R-SERVER, ldirectord只能实现一种功能,那就是健康检测R-SERVER,当R-SREVER出现问题时,能及时通过调用ipvsadm将问题R-SERVER从规则当中踢出。我们在这篇博文时主要演示一下第二种方案。
实现过程
拓扑:
- 下载并安装idrectord
//安装包可以向我索要,很多yum里面都没有
yum localinstall ldirectord-3.9.6-0rc1.1.1.x86_64.rpm
[root@lvs ~]# rpm -ql ldirectord
/etc/ha.d
/etc/ha.d/resource.d
/etc/ha.d/resource.d/ldirectord
/etc/logrotate.d/ldirectord
/usr/lib/ocf/resource.d/heartbeat/ldirectord
/usr/lib/systemd/system/ldirectord.service
/usr/sbin/ldirectord
/usr/share/doc/ldirectord-3.9.6
/usr/share/doc/ldirectord-3.9.6/COPYING
/usr/share/doc/ldirectord-3.9.6/ldirectord.cf
/usr/share/man/man8/ldirectord.8.gz
- 将模板配置文件cp到主目录下
cp /usr/share/doc/ldirectord-3.9.6/ldirectord.cf /etc/ha.d/
- 解释主配置文件
# Global Directives
checktimeout=3 健康检测超时时间3秒,也就说三秒不通才能判定R-SERVER宕机了
checkinterval=1 一秒检查一次
#fallback=127.0.0.1:80 如果所有的R-SERVER都宕机了,谁来响应,通常是本机说sorry
autoreload=yes 自动重载
#logfile="/var/log/ldirectord.log" 日志相关
#logfile="local0" 日志发送到rsyslog
#emailalert="admin@x.y.z" 邮件相关
#emailalertfreq=3600
#emailalertstatus=all
quiescent=no
# Sample for an http virtual service
virtual=192.168.80.99:80 #vip
real=192.168.80.11:80 gate #-g代表DR模型
real=192.168.80.12:80 gate
service=http #检测协议
scheduler=rr #rr算法
#persistent=600
#netmask=255.255.255.255
protocol=tcp
checktype=negotiate
checkport=80
request="index.html" #请求的默认界面
receive="80" #界面当中必须要用什么字符才能判定没有问题
#virtualhost=www.x.y.z
- 配置示例
[root@lvs ~]# vim /etc/ha.d/ldirectord.cf
# Global Directives
checktimeout=3
checkinterval=1
#fallback=127.0.0.1:80
autoreload=yes
#logfile="/var/log/ldirectord.log"
#logfile="local0"
#emailalert="admin@x.y.z"
#emailalertfreq=3600
#emailalertstatus=all
quiescent=no
# Sample for an http virtual service
virtual=192.168.80.99:80
real=192.168.80.11:80 gate
real=192.168.80.12:80 gate
fallback=127.0.0.1:80 gate
service=http
scheduler=rr
#persistent=600
#netmask=255.255.255.255
protocol=tcp
checktype=negotiate
checkport=80
request="index.html"
receive="80"
#virtualhost=www.x.y.z
//清空规则,让此服务接管
ipvsadm -C
//启动服务
systemctl restart ldirectord.service
[root@lvs ~]# ipvsadm -Ln
TCP 192.168.80.99:80 rr
-> 192.168.80.11:80 Route 1 0 0
-> 192.168.80.12:80 Route 1 0 0