欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
负载均衡的方案有很多,适合RabbitMQ使用的处理HAProxy之外还有LVS。LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分,在Linux2.6.32内核以前,使用LVS时必须要重新编译内核以支持LVS功能模块,但是从Linux2.6.32内核以后,已经完全内置了LVS的各个功能模块,无需给内核打任何补丁,可以直接使用LVS提供的各种功能。
LVS是4层负载均衡,也就是说建立在OSI模型的传输层之上。LVS支持TCP/UDP的负载均衡,相对于其它高层负载均衡的解决方案,比如DNS域名轮流解析、应用层负载的调度、客户端的调度等,它是非常高效的。LVS自从1998年开始,发展到现在已经是一个比较成熟的技术项目了。可以利用LVS技术实现高可伸缩的、高可用的网络服务,例如WWW服务、Cache服务、DNS服务、FTP服务、MAIL服务、视频/音频点播服务等等,有许多比较著名网站和组织都在使用LVS架设的集群系统,例如:Linux的门户网站(www.linux.com)、向RealPlayer提供音频视频服务而闻名的Real公司(www.real.com)、全球最大的开源网站(sourceforge.net)等。
LVS主要由3个部分组成:
- 负载调度器(Load Balancer/ Director):它是整个集群对外面的前端机,负责将客户的请求发送到一组服务器上执行,而客户认为服务是来自一个IP地址(VIP)上的。
- 服务器池(Server Pool/ RealServer):是一组真正执行客户端请求的服务器,如RabbitMQ服务器。
- 共享存储(Shared Storage):它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。
目前LVS的负载均衡方式也分为三种:
- VS/NAT:即Virtual Server via Network Address Translation的简称。VS/NAT是一种最简单的方式,所有的RealServer只需要将自己的网关指向Director即可。客户端可以是任意的操作系统,但此方式下,一个Director能够带动的RealServer比较有限。
- VS/TUN:即Virtual Server via IP Tunneling的简称。IP隧道(IP Tunneling)是将一个IP报文封装再另一个IP报文的技术,这可以使得目标为一个IP地址的数据报文能够被封装和转发到另一个IP地址。IP隧道技术亦可以称之为IP封装技术(IP encapsulation)。
- VS/DR:即Virtual Server via Direct Routing的简称。VS/DR方式是通过改写报文中的MAC地址部分来实现的。Director和RealServer必须在物理上有一个网卡通过不间断的局域网相连。RealServer上绑定的VIP配置在各自Non-ARP的网络设备上(如lo或tunl),Director的VIP地址对外可见,而RealServer的VIP对外是不可见的。RealServer的地址即可以是内部地址,也可以是真实地址。
对于LVS而言配合Keepalived一起使用同样可以实现高可靠的负载均衡,对于图7-11来说,LVS可以完全的替代HAProxy而其他内容可以保持不变。LVS不需要额外的配置文件,直接集成在Keepalived的配置文件之中。修改/etc/keepalived/keepalived.conf文件内容如下:
#Keepalived配置文件(Master)
global_defs {
router_id NodeA #路由ID, 主备的ID不能相同
}
vrrp_instance VI_1 {
state MASTER #Keepalived的角色。Master表示主服务器,从服务器设置为BACKUP
interface eth0 #指定监测网卡
virtual_router_id 1
priority 100 #优先级,BACKUP机器上的优先级要小于这个值
advert_int 1 #设置主备之间的检查时间,单位为s
authentication { #定义验证类型和密码
auth_type PASS
auth_pass root123
}
track_script {
chk_haproxy
}
virtual_ipaddress { #VIP地址,可以设置多个:
192.168.0.10
}
}
virtual_server 192.168.0.10 5672 { #设置虚拟服务器
delay_loop 6 #设置运行情况检查时间,单位是秒
#设置负载调度算法,共有rr,wrr,lc,wlc,lblc,lblcr,dh,sh这8种。
lb_algo wrr #这里是加权轮询
lb_kind DR #设置LVS实现的负载均衡机制方式VS/DR
#指定在一定的时间内来自同一IP的连接将会被转发到同一RealServer中。
persistence_timeout 50
protocal TCP #指定转发协议类型,有TCP和UDP两种
#这个real_server即指LVS的三大部分之一的RealServer,这里特指RabbitMQ的服务
real_server 192.168.0.2 5672 { #配置服务节点
weight 1 #配置权重
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 5672
}
}
real_server 192.168.0.3 5672 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 5672
}
}
real_server 192.168.0.4 5672 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 5672
}
}
}
#为RabbitMQ的rabbitmq_management插件设置负载均衡
virtual_server 192.168.0.10 15672 {
delay_loop 6
lb_algo wrr
lb_kind DR
persistence_timeout 50
protocal TCP
real_server 192.168.0.2 15672 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 15672
}
}
real_server 192.168.0.3 15672 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 15672
}
}
real_server 192.168.0.4 15672 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 15672
}
}
}
对于Backup的配置可以参考前一小节中的相应配置。在LVS和Keepalived环境里面,LVS主要的工作是提供调度算法,把客户端请求按照需求调度在RealServer,Keepalived主要的工作是提供LVS控制器的一个冗余,并且对RealServer做健康检查,发现不健康的RealServer就把它从LVS集群中剔除,RealServer只负责提供服务。
通常在LVS的VS/DR模式下需要在RealServer上配置VIP。原因在于当LVS把客户端的包转发给RealServer时,因为包的目的IP地址是VIP,那么如果RealServer收到这个包后发现包的目的地址不是自己系统的IP,那么就会认为这个包不是发给自己的,就会丢弃这个包,所以需要将这个IP地址绑定到网卡下。当发送应答包给客户端时,RealServer就会把包的源和目的地址调换,直接回复给客户端。下面为所有的RealServer的的lo:0网卡创建启动脚本(vim /opt/realserver.sh)绑定VIP地址,详细内容如下:
#!/bin/bash
VIP=192.168.0.10
/etc/rc.d/init.d/functions
case "$1" in
start)
/sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP
/sbin/route add -host $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)
/sbin/ifconfig lo:0 down
/sbin/route del -host $VIP dev lo:0
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
;;
status)
islothere=`/sbin/ifconfig lo:0 | grep $VIP | wc -l`
isrothere=`netstat -rn | grep "lo:0"|grep $VIP | wc -l`
if [ $islothere -eq 0 ]
then
if [ $isrothere -eq 0 ]
then
echo "LVS of RealServer Stopped."
else
echo "LVS of RealServer Running."
fi
else
echo "LVS of RealServer Running."
fi
;;
*)
echo "Usage:$0{start|stop}"
exit 1
;;
esac
注意上面绑定VIP的掩码是255.255.255.255,说明广播地址使其自身,那么它就不会将ARP发送到实际的自己该属于的广播域了,这样防止与LVS上的VIP冲突进而导致IP地址冲突。为/opt/realserver.sh文件添加可执行权限后,运行/opt/realserver.sh start命令之后可以通过ip add show命令查看lo:0网卡的状态,注意与Keepalived节点的网卡状态进行区分。
[root@node1 keepalived]# ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 192.168.0.10/32 brd xx.xx.197.74 scope global lo:0
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:5e:7a:f7 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/18 brd xx.xx.255.255 scope global eth0
inet6 fe80::f816:3eff:fe5e:7af7/64 scope link
valid_lft forever preferred_lft forever
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。