Lvs 负载均衡
负载均衡集群是 Load Balance 集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端提供服务的一种方式。常用
的负载均衡。
开源软件有Nginx、LVS、Haproxy (ngnix和haproxy是七层负载均衡,LVS是四层负载均衡)
商业的硬件负载均衡设备F5、Netscale。
简单的理解一下软件负载均衡。①.所谓分层的负载均衡,都是以网络的模型来说的。四层就是基于IP和端口的负载均衡,七层就是基于URL等应用
信息的负载均衡。所以简单的说四层负载均衡就是通过IP和端口接收请求再分发至真实的服务器,七层是通过URL或主机名接收请求,然后分发至真实
的服务器。②.而七层的实现也是在四层的基础上是实现的,没有四层就不可能有七层。在第七层上可以做许多事情,比如可以根据七层的浏览器类别区
分是手机还是PC,将WEB服务器分为2组,手机登陆专门的移动端网站。③.对客户端来说,客户端好像是访问的同一台主机。其实为了有更好的用户体
验,从智能DNS入手,根据客户端IP来源将域名解析到距离客户端最近的一台服务器或者访问最快速的一台服务器,但这些内容客户端都是感觉不到的,
客户端感觉到的只能是访问网站很快。
负载均衡的原理很简单,就是当客户端发起请求时,请求直接发给Director Server(调度器),这时会根据设定
的调度算法,将请求按照算法的规定智能的分发到真正的后台服务器。以达到将压力均摊。但是我们知道,http的
连接时无状态的,假设这样一个场景,我登录某宝买东西,当我看上某款商品时,我将它加入购物车,但是我刷新
了一下页面,这时由于负载均衡的原因,调度器又选了新的一台服务器为我提供服务,我刚才的购物车内容全都不
见了,这样就会有十分差的用户体验。所以就还需要一个存储共享,这样就保证了用户请求的数据是一样的。所以
LVS负载均衡分为3层:
第一层:负载调度器(load balancer/Director),它是整个集群的总代理,它在有两个网卡,一个网卡面对访问网站的客户端,
一个网卡面对整个集群的内部。负责将客户端的请求发送到一组服务器上执行,而客户也认为服务是来自这台主的。举个生动
的例子,集群是个公司,负载调度器就是在外接揽生意,将接揽到的生意分发给后台的真正干活的真正的主机们。当然需要将活
按照一定的算法分发下去,让大家都公平的干活。
第二层:服务器池(server pool/ Realserver),是一组真正执行客户请求的服务器,可以当做WEB服务器。就是上面例子中的小员工。
第三层:共享存储(sharedstorage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。一个公司得有一个后台账目吧,这才能协调。不然客户把钱付给了A,而换B接待客户,因为没有相同的账目。B说客户没付钱,那这样就不是客户体验度的问题了。
lvs原理图
LVS的实现原理
lvs的原理其实就是利用了Iptables的功能。了解防火墙的都知道四表五链。防火墙不仅仅有放火的功能还有转发,地址伪装,限流等等功能
首先,客户端向调度器(Director Server)发起一个请求,调度器将这个请求发送至内核
PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链。
当请求达到INPUT链上,调度器判断报文中的目标端口来确定这个访问是不是要访问集群服务(因为还有可能只是ssh想单纯的远程登录主机这个主机),如果是访问的集群服务,那么就会强制修改这个包的目标IP
POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器
lvs实现原理
LVS 由2部分程序组成,包括 ipvs 和 ipvsadm。
ipvs(ip virtual server):一段代码工作在内核空间,叫ipvs,是真正生效实现调度的代码。
ipvsadm:另外一段是工作在用户空间,叫ipvsadm,负责为ipvs内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(Real Server)
前面已经说了,调度器(directory) 是通过一定的调度算法将服务请求一个一个的分发下去。现在了解一下调度算法
LVS一共有10种调度算法。
静态调度算法(4个)
1.rr(轮叫调度)
轮叫调度:这种是最简单的调度算法,就是将请求A一个,B一个,A一个,B一个 ...... 循环的发。就算A主机挂掉了,调度器还是会将请求发送到A。十分均衡。
2.wrr(加权轮叫)
加权轮叫调度:这种算法是在rr基础上实现的,只不过加了权重,权重范围为1-100,假设A的服务器性能好,就给A的权重设置的高一点,设为2,而B主机是1。这样就实现A二个,B一个,A二个,B一个 ...... 循环的发。这样照顾到了服务器性能。
3.sh(源地址哈希)
源地址散列:主要是实现将此前的session(会话)绑定。将此前客户的源地址作为散列键,从静态的散列表中找出对应的服务器,只要目标服务器是没有超负荷的就将请求发送过去。就是说某客户访问过A,现在这个客户又来了,所以客户请求会被发送到服务过他的A主机。
4.dh(目的地址哈希)
目的地址散列:以目的地址为关键字查找一个静态hash表来获得需要的RS。以目标地址为标准挑选。 功能是和sh近似的,但应用场景不同
(dh举个例子:假设1号客户访问了web集群的一个动态页面,调度器将请求转发个A服务器,A服务器的PHP将这个动态请求运行了一遍,生成了缓存并回应1号客户。这下2号客户也访问了这个动态页面,调度器应该将请求发给A。毕竟A已经跑过这段程序了,有缓存,对吧。所以这既是dh算法)
接下来是动态算法,动态算法与静态算法最大的区别就是动态算法考虑了服务器的压力。
活动链接(active):客户与服务器建立连接并且有数据传送
非活动链接(inactive):只是建立连接,没有数据传送,没有断开连接
动态调度算法(6个)
1.lc(最少链接)
最少连接调度:这种算法是看A,和B的主机谁的连接少,请求就发给谁。
简单算法:active*256+inactive (谁小发给谁)
2.wlc(加权最少链接)LVS的理想算法
加权最少链接:这种算法就是比lc多了一个加权。
简单算法:( active*256+inactive )/weight (谁小就发给谁)
3.sed(最短期望延迟)
基于wlc算法,假设A,B的权重分别是1,2 。而A的链接数为1,B的链接数为2 。这样的话,用wlc算法得出的结果一样,而明显B的权重大,B的能力较强。用sed算法的话,就可以避免wlc出现的问题。
简单算法:(active+1)*256/weight (活动的连接数+1)*256/除以权重 谁小发给谁
A:(1+1)/1
B:(2+1)/2 (B小,交给B)
4.nq(用不排队)
基于sed算法:在sed的基础上,若谁的链接数为0,直接将请求发送给他,没二话
5.LBLC(基于局部性的最少连接)类似于dh,目标地址hash
这个算法主要用于Cache集群系统,因为Cache集群的中客户请求报文的目标IP地址的变化,将相同的目标URL地址请求调度到同一台服务器,来提高服务器的访问的局部性和Cache命中率。从而调整整个集群的系统处理能力。但是,如果realserver的负载处于一半负载,就用最少链接算法,将请求发送给活动链接少的主机。
6.LBLCR(带复制的基于局部性的最少链接)
该算法首先是基于最少链接的,当一个新请求收到后,一定会将请求发给最少连接的那台主机的。但这样又破坏了cache命中率。但这个算法中,集群服务是cache共享的,假设A的PHP跑了一遍,得到缓存。但其他realserver可以去A那里拿缓存,这是种缓存复制机制。
LVS 负载均衡集群系统的优点:
1、提高吞吐量
想获得更高的吞吐量,在 LVS 中只需增加 Real-server 即可,其开销只是线性增长。如选择更换一台更高性能的服务器来获得相当的吞吐量,开销要大很多。
2、冗余
如果 LVS 中某台 Real-server 由于需要升级或其它原因不能对外提供服务,其退出及恢复工作并不会对用户造成服务中断。
3、适应性
不管是需要吞吐量逐渐变化、还是快速变化,服务器的增减对客户都是透明的。
LVS的工作原理
LVS 的工作模式分为4中分别是 NAT,DR,TUN,FULL-NAT。其中做个比较,由于工作原理的关系的,NAT的配置最为简单,但是NAT对调度器的压力太大了,导致其效率最低,DR和TUN的工作原理差不多,但是DR中,所有主机必须处于同一个物理环境中,而在TUN中,所有主机可以分布在不同的位置,服务器一个在纽约,一个在深圳。最多应用的是FULL-NAT。
LVS 负载均衡集群系统转发机制:
Virtual Server via NAT ( VS/NAT )
VS/NAT 网络地址转换模式,服务器可以运行任何支持 TCP/IP 协议的操作系统,它只需要一个公网 IP 地址配置在 LVS 主机上,后端真实服务器都可以使用私有地址。
它的缺点是扩充能力有限,当后端真实服务器达到一定数量时,LVS 本机有可能成为集群瓶颈,因为整个集群中的客户端请求和响应封包都要通过 LVS 负载均衡主机。
LVS/NAT原理和特点
NAT方式的实现原理和数据包的改变。
(a). 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP
(b). PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
(c). IPVS比对数据包请求的服务是否为集群服务,若是,修改数据包的目标IP地址为后端服务器IP,然后将数据包发至POSTROUTING链。 此时报文的源IP为CIP,目标IP为RIP
(d). POSTROUTING链通过选路,将数据包发送给Real Server
(e). Real Server比对发现目标为自己的IP,开始构建响应报文发回给Director Server。 此时报文的源IP为RIP,目标IP为CIP
(f). Director Server在响应客户端前,此时会将源IP地址修改为自己的VIP地址,然后响应给客户端。 此时报文的源IP为VIP,目标IP为CIP
LVS-NAT模型的特性
RS应该使用私有地址,RS的网关必须指向DIP
DIP和RIP必须在同一个网段内
请求和响应报文都需要经过Director Server,高负载场景中,Director Server易成为性能瓶颈
支持端口映射
RS可以使用任意操作系统
缺陷:对Director Server压力会比较大,请求和响应都需经过director server
3、Virtual Server via Direct Routing ( VS/DR )
lVS/DR 直接路由模式,同样 LVS 主机只处理客户端到服务器端的连接,响应信息由真实服务器直接返回给客户端。
DR 模式要求所有真实服务器必须至少有一块网卡与 LVS 主机在同一物理网段中,且真实服务器网络设备或设备别名不作 ARP 响应。
Keepalived 起初是 LVS 设计的,专门用来监控集群系统中各个服务节点的状态,后来又加入了 VRRP( 虚拟路由冗余协议 )解决静态路由出现的单点故障问题,
通过 VRRP 协议可以实现网络不间断稳定运行。因此,Keepalived 不仅具有服务器状态检测和故障隔离功能,还具有 HA Cluster 功能。
Keepalived 作为 LVS 的扩展项目,因此。Keepalived 可以与 LVS 无缝整合,轻松构建一套高性能的负载均衡集群系统。
LVS/DR原理和特点
重将请求报文的目标MAC地址设定为挑选出的RS的MAC地址
当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP
REROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
IPVS比对数据包请求的服务是否为集群服务,若是,将请求报文中的源MAC地址修改为DIP的MAC地址,将目标MAC地址修改RIP的MAC地址,然后将数据包 发至POSTROUTING链。 此时的源IP和目的IP均未修改,仅修改了源MAC地址为DIP的MAC地址,目标MAC地址为RIP的MAC地址
由于DS和RS在同一个网络中,所以是通过二层来传输。POSTROUTING链检查目标MAC地址为RIP的MAC地址,那么此时数据包将会发至Real Server。
RS发现请求报文的MAC地址是自己的MAC地址,就接收此报文。处理完成之后,将响应报文通过lo接口传送给eth0网卡然后向外发出。 此时的源IP地址为VIP,目标IP为CIP
响应报文最终送达至客户端
LVS-DR模型的特性
特点1:保证前端路由将目标地址为VIP报文统统发给Director Server,而不是RS
RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问
RS跟Director Server必须在同一个物理网络中
所有的请求报文经由Director Server,但响应报文必须不能进过Director Server
不支持地址转换,也不支持端口映射
RS可以是大多数常见的操作系统
RS的网关绝不允许指向DIP(因为我们不允许他经过director)
RS上的lo接口配置VIP的IP地址
缺陷:RS和DS必须在同一机房中
TUN模式
和DR模式差不多,但是比DR多了一个隧道技术以支持realserver不在同一个物理环境中。就是realserver一个在北京,一个工作在上海。
在原有的IP报文外再次封装多一层IP首部,内部IP首部(源地址为CIP,目标IIP为VIP),外层IP首部(源地址为DIP,目标IP为RIP
(a) 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP 。
(b) PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
(c) IPVS比对数据包请求的服务是否为集群服务,若是,在请求报文的首部再次封装一层IP报文,封装源IP为为DIP,目标IP为RIP。然后发至POSTROUTING链。 此时源IP为DIP,目标IP为RIP
(d) POSTROUTING链根据最新封装的IP报文,将数据包发至RS(因为在外层封装多了一层IP首部,所以可以理解为此时通过隧道传输)。 此时源IP为DIP,目标IP为RIP
(e) RS接收到报文后发现是自己的IP地址,就将报文接收下来,拆除掉最外层的IP后,会发现里面还有一层IP首部,而且目标是自己的lo接口VIP,那么此时RS开始处理此请求,处理完成之后,通过lo接口送给eth0网卡,然后向外传递。 此时的源IP地址为VIP,目标IP为CIP
(f) 响应报文最终送达至客户端
LVS-TUN的特点
1. RIP、VIP、DIP全是公网地址
2.RS的网关不会也不可能指向DIP
3.不支持端口映射
4.RS的系统必须支持隧道
fullNAT 模式
lvs fullnat应用模式通过TCP三次握手的ack,ack+data报文将client端的真实IP地址插入到tcp options中从而带给后端的realserver。而后端realserver toa内核模块中通过hook了tcp_v4_syn_recv_sock()函数,然后调用get_toa_data()从tcp_options中取得客户端的真实IP地址,具体的调用过程下边分析。
看完上图后发现 FULLNAT有一个问题是:RealServer无法获得用户IP;淘宝通过叫TOA的方式解决的,
主要原理是:将client address放到了TCP Option里面带给后端RealServer,RealServer收到后保存在socket
的结构体里并通过toa内核模块hook了getname函数,这样当用户调用getname获取远端地址时,返回的是保
存在socket的TCPOption的IP. 百度的BVS是通过叫ttm模块实现的,其实现方式跟toa基本一样,只是没有开源.
实现原理图如下:
LVS 负载均衡 + keepalived 部署
DR 模式
利用ipvsadm内核功能,(不需要开启,用户层面需要控制这个服务,调用脚本来保存)策略)
安装 这个ipvsadm-1.26-2.el6.x86_64 必须配置yum 源
cat /etc/yum.repos.d/rhel-source.repo
[rhel-source]
name=Red Hat Enterprise Linux $releasever - $basearch - Source
baseurl=http://172.25.254.53/rhel6.5
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
[HighAvailability]
name=HighAvailability
baseurl=http://172.25.254.53/rhel6.5/HighAvailability
gpgcheck=0
[ResilientStorage]
name=ResilientStorage
baseurl=http://172.25.254.53/rhel6.5/ResilientStorage
gpgcheck=0
[ScalableFileSystem]
name=ScalableFileSystem
baseurl=http://172.25.254.53/rhel6.5/ScalableFileSystem
gpgcheck=0
[LoadBalancer]
name=LoadBalancer
baseurl=http://172.25.254.53/rhel6.5/LoadBalancer
gpgcheck=0
在server 1 服务器中 配置
在server 2中
在server 3 中
在你的物理机中测试是否实现轮询
然后查看100IP 的MAC地址所对应的 ip
keepalived 安装与部署
安装所需要的 两个包
keepalived-1.4.1.tar.gz libnfnetlink-devel-1.0.0-1.el6.x86_64.rpm
tar zxf keepalived-1.4.1.tar.gz 解压包
yum install gcc libnl libnl-devel openssl-devel libnfnetlink-devel-1.0.0-1.el6.x86_64.rpm 安装
./configure --prefix=/usr/local/keepalived --with-init=SYSV 编译检查
make && make install
做一个软链接
[root@server1 ~]# ln -s /usr/local/keepalived/etc/keepalived/ /etc/
[root@server1 ~]# ln -s /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
[root@server1 ~]# ln -s /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
[root@server1 ~]# ln -s /usr/local/keepalived/sbin/keepalived /sbin/
[root@server1 ~]# chmod +x /etc/init.d/keepalived
/etc/init.d/keepalived start
/etc/init.d/keepalived stop
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost ###接受报警的邮箱
}
notification_email_from keepalived@localhost ##邮件发送者
smtp_server 127.0.0.1 ##
smtp_connect_timeout 30 ##连接smtp的超时时间
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER #备机需要改为BACKUP
interface eth1 #高可用的检测网络接口
virtual_router_id 51 #主和备机的id必须一样,且在0~255
priority 100 #主机的优先级,备机应该此值小点
advert_int 1 #主备之间的通告时间间隔秒数
authentication {
auth_type PASS #设置验证类型
auth_pass 1111 #设置验证密码
}
virtual_ipaddress {
172.25.254.10 #VIP
}
}
virtual_server 172.25.254.131 80 {
delay_loop 6 #每隔4秒查询realserver的状态
lb_algo rr #rr论叫算法
lb_kind DR #LVS的DR模式
#persistence_timeout 50 #保持会话使用的时常ftp服务类型
protocol TCP ##tcp协议
real_server 172.25.254.132 80 { ##RS
weight 1 #权重
TCP_CHECK { #realserver的状态检测设置部分
connect_timeout 3 #3秒无响应超时
retry 3 #重试次数
delay_before_retry 3 #重试间隔
}
}
real_server 172.25.254.133 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
在辅助调度器中 server 4 做相同的动作
[root@host4 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 51
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.131
}
}
virtual_server 172.25.254.131 80 {
delay_loop 6
lb_algo rr
lb_kind DR
#persistence_timeout 50
protocol TCP
real_server 172.25.254.132 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 172.25.254.133 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
测试
高可用 当主调度器host1 down掉,备用调度器会接替工作
/etc/init.d/keepalived stop
在执行
健康检查 当其中一个server2 关闭服务或者出现故障 server 3 正常工作
[root@foundation53 ~]# curl 172.25.254.131
server133