LVS 实现负载均衡的原理


LVS 负载均衡          


负载均衡集群是 Load Balance 集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端提供服务的一种方式。常用
的负载均衡。开源软件有Nginx、LVS、Haproxy      (ngnix和haproxy是七层负载均衡,LVS是四层负载均衡) 商业的硬件负载均衡设备F5、Netscale。简单的理解一下软件负载均衡。①.所谓分层的负载均衡,都是以网络的模型来说的。四层就是基于IP和端口的负载均衡,七层就是基于URL等应用信息的负载均衡。所以简单的说四层负载均衡就是通过IP和端口接收请求再分发至真实的服务器,七层是通过URL或主机名接收请求,然后分发至真实
的服务器。②.而七层的实现也是在四层的基础上是实现的,没有四层就不可能有七层。在第七层上可以做许多事情,比如可以根据七层的浏览器类别区
分是手机还是PC,将WEB服务器分为2组,手机登陆专门的移动端网站。③.对客户端来说,客户端好像是访问的同一台主机。其实为了有更好的用户体
验,从智能DNS入手,根据客户端IP来源将域名解析到距离客户端最近的一台服务器或者访问最快速的一台服务器,但这些内容客户端都是感觉不到的,
客户端感觉到的只能是访问网站很快。

         

一.负载均衡LVS的介绍

      负载均衡的原理很简单,就是当客户端发起请求时,请求直接发给Director Server(调度器),这时会根据设定
的调度算法,将请求按照算法的规定智能的分发到真正的后台服务器。以达到将压力均摊。但是我们知道,http的
连接时无状态的,假设这样一个场景,我登录某宝买东西,当我看上某款商品时,我将它加入购物车,但是我刷新
了一下页面,这时由于负载均衡的原因,调度器又选了新的一台服务器为我提供服务,我刚才的购物车内容全都不
见了,这样就会有十分差的用户体验。所以就还需要一个存储共享,这样就保证了用户请求的数据是一样的。所以
LVS负载均衡就分为3层:

     ☆ 第一层:负载调度器(load balancer/ Director),它是整个集群的总代理,它在有两个网卡,一个网卡面对访问网站的客户端,

一个网卡面对整个集群的内部。负责将客户端的请求发送到一组服务器上执行,而客户也认为服务是来自这台主的。举个生动

的例子,集群是个公司,负载调度器就是在外接揽生意,将接揽到的生意分发给后台的真正干活的真正的主机们。当然需要将活

按照一定的算法分发下去,让大家都公平的干活。

     ☆第二层:服务器池(server pool/ Realserver),是一组真正执行客户请求的服务器,可以当做WEB服务器。就是上面例子中的

小员工。  

      ☆第三层:共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相

同的服务。一个公司得有一个后台账目吧,这才能协调。不然客户把钱付给了A,而换B接待客户,因为没有相同的账目。B说客户

没付钱,那这样就不是客户体验度的问题了。

lvs 的原理示意图

二.LVS的实现原理

           lvs的原理其实就是利用了Iptables的功能。了解防火墙的都知道四表五链。防火墙不仅仅有放火的功能还有转发,地址伪装,限流等等功能。


lvs实现原理

①.首先,客户端向调度器(Director Server)发起一个请求,调度器将这个请求发送至内核

②.PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链。

③.当请求达到INPUT链上,调度器判断报文中的目标端口来确定这个访问是不是要访问集群服务(因为还有可能只是ssh想单纯的远程登录主机这个主机),如果是访问的集群服务,那么就会强制修改这个包的目标IP

④.POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器

三.LVS的组成

         1.lvs分为两个部分,分别是内核模块和lvs的管理工具

目前来说,centos6及其以上的内核版本已经包括了ipvs的相关模块了

内核支持的ipvs模块

    上图中的rr,wrr,lc,wlc,lblc等等都是lvs中调度器的调度算法,根据不同的调度算法可以更好的分配服务,实现负载均衡。

而ipvs(ip virtual server):一段代码工作在内核空间,实现调度。

   

ipvsadm客户端管理工具

     上图是ipvsadm。负责为ipvs内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(Real Server)。


四.LVS的调度算法

       前面已经说了,调度器(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那里拿缓存,这是种缓存复制机制。


    最后聊一下http这个协议,因为上面都有一些包含会话(session),COOKIE等名词新手可能会陌生。

    当用户访问一台web服务器时,服务器会返回一个客户标示信息。这个信息就是COOKIE。COOKIE会被保存在客户端的浏览器缓存中,那么这个COOKIE是干什么的呢。

    因为http是无状态的,服务器并不知道之前有谁访问了自己。那这就出现了一个问题,假设客户访问了一个需要登录的网页,可http无状态,刚登陆过的客户,服务器又不知道他是谁了。为了解决这个问题就出现了COOKIE。客户端首次访问时得到COOKIE,下次再访问时拿着这个COOKIE去访问服务器,服务器就认识客户端了,知道他是已经登录过的用户。所以COOKIE就是服务器用来追踪客户端的身份的。

   服务器端为每一个客户保存一个COOKIE和客户端的对应,这就是回话(session)。session里保存了客户访问的url,对应COOKIE等等。

   在某些特殊场景中需要realserver做到session共享,同步session

五.LVS的工作原理

    LVS 的工作模式分为4中分别是 NAT,DR,TUN,FULL-NAT。其中做个比较,由于工作原理的关系的,NAT的配置最为简单,但是NAT对调度器的压力太大了,导致其效率最低,DR和TUN的工作原理差不多,但是DR中,所有主机必须处于同一个物理环境中,而在TUN中,所有主机可以分布在不同的位置,服务器一个在纽约,一个在深圳。最多应用的是FULL-NAT。


其中的专业术语

1. DS:Director Server。指的是前端负载均衡器。
2. RS:Real Server。后端真实的工作服务器。
3. VIP:向外部直接面向用户请求,作为用户请求的目标的IP地址。
4. DIP:Director Server IP,主要用于和内部主机通讯的IP地址。
5. RIP:Real Server IP,后端服务器的IP地址。
6. CIP:Client IP,访问客户端的IP地址。

    1.NAT模式

nat模式

     客户发出请求,发送请求给链接调度器的VIP,调度器将请求报文中的目标Ip地址改为RIP。这样服务器RealServer将请求的内容发给调度器,调度器再将报文中的源IP地址改为VIP。

    

           (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

    

 Nat模型的特点

1.很好配置,原理简单易懂

2.由于调度器的工作量太大,很容易成为整个集群系统的瓶颈。

3.RS应该使用私有地址,RS的网关必须指向DIP

4.支持端口映射

   2.DR模式

   整个DR模式都是停留在第二层的数据链路层。直接修改MAC。实现报文的转发。

                           

                                                                                                  dr模式

                      (a) 当用户请求到达Director Server,此时请求的数据报文会先到内核空间的PREROUTING链。 此时报文的源IP为CIP,目标IP为VIP
                   (b) PREROUTING检查发现数据包的目标IP是本机,将数据包送至INPUT链
                   (c) IPVS比对数据包请求的服务是否为集群服务,若是,将请求报文中的源MAC地址修改为DIP的MAC地址,将目标MAC地址修改RIP的MAC地址,然后将数据包发至POSTROUTING链。 此时的源IP和目的IP均未修改,仅修改了源MAC地址为DIP的MAC地址,目标MAC地址为RIP的MAC地址
                   (d) 由于DS和RS在同一个网络中,所以是通过二层来传输。POSTROUTING链检查目标MAC地址为RIP的MAC地址,那么此时数据包将会发至Real Server。
                   (e) RS发现请求报文的MAC地址是自己的MAC地址,就接收此报文。处理完成之后,将响应报文通过lo接口传送给eth0网卡然后向外发出。 此时的源IP地址为VIP,目标IP为CIP
                   (f) 响应报文最终送达至客户端

    

LVS-DR的特点

1.在前端路由器做静态地址路由绑定,将对于VIP的地址仅路由到Director Server

2.arptables:在arp的层次上实现在ARP解析时做防火墙规则,过滤RS响应ARP请求。

修改RS上内核参数(arp_ignore和arp_announce)将RS上的VIP配置在网卡接口的别名上,并限制其不能响应对VIP地址解析请求。

                                      

        3.TUN模式

           和DR模式差不多,但是比DR多了一个隧道技术以支持realserver不在同一个物理环境中。就是realserver一个在北京,一个工作在上海

                 在原有的IP报文外再次封装多一层IP首部,内部IP首部(源地址为CIP,目标IIP为VIP),外层IP首部(源地址为DIP,目标IP为RIP

        

tun模式

              (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的系统必须支持隧道

六.LVS的DR实现

  1,准备工作,3台主机。一台调度器(DS),2台真实主机(RS)


其中VIP是虚拟IP,三个主机都要配置这个VIP,

2.给三个主机配置虚拟ip。每台主机都需要配置。(三个主机都需要配置) realserver配置到lo接口上。


    2台realserver修改内核参数,防止VIP相应arp协议

 


         这里必须说明一下,IP是属于主机的,IP不属于网卡,假如100这个IP在lo接口上,而11在eth0上。当局域网有人请求100的IP的arp请求时,虽然IP在lo上,该主机还是会相应的,只不过,100会流经可以相应的eth0这个网卡。所以,内核就有将arp请求屏蔽的不同级别。而某台主机一接入局域网中,他就会向全局域网发广播,我上线了。

          arp_announce :

          0: 将本机的IP通过任何接口向外界通告

          1:试图仅向目标网络与其网络匹配的地址

          2:仅向与本地接口上的地址匹配的网络进行通告

          arp_ignore:

         0:

         1:仅在请求的目标地址配置请求到达接口上的时候,才相应


或者安装arp防火墙,执行如下命令。

yum -y install arptable_jf

arptables -A IN -d 192.168.2.100 -j DROP

arptables -A OUT -s 192.168.2.100 -j mangle --mangle-ip-s 192.168.2.11


3.给调度器安装ipvsadm

 

再配置相关ipvsadm 规则

 

查看效果

                                           


七.LVS+Heartbeat+ldirectory

            这时需要加一个directory,在两个directory中做负载均衡。需要在2个directory安装heartbeat和ldirectory。

       

          拷贝配置文件过来并,修改权限。

    

        修改相关配置文件。具体可以参考    heartbeat集群搭建

        特别注意haresources要加上ldirectord这个服务的启动脚本

     


     配置 ldiectord

    复制ldiectord的配置文件到/etc/ha.d下


    修改成如下模式

    

              



  启动heartbeat。观察效果。效果是,如果一个realserver挂了。他会自动不会转发请求给挂掉的realserver


   service heartbeat start  

   当正常时。还是上个实验的结果

   当realser1坏掉后。realser1 自动被移出集群


  当realser1和realser2都坏了的话。directory自动顶上去,并显示web崩溃

   


八。LVS+keepalived集群。

   安装源码包编译需要的工具。并下载keepalived的源码包。  (两个节点都需要做)

gcc 和 openssl-devel

    wget http://www.keepalived.org/software/keepalived-1.2.5.tar.gz       这命令从keepalived官网下载keepalived源码包。

    解压并且编译。

   

黑色部分是重点

    configure 后以后再 make和make install。这就不说了,编译三部曲。

    把配置文件都链接到正常的文件夹中。

   

软链接

   vi /etc/keepalived/keepalived.conf 编辑配置文件。(写完了给备机一份,但有些个别地方要改改)

内容如下



! Configuration File for keepalived
global_defs {
notification_email {
root@localhost#接受报警的邮箱
}
notification_email_from keepalived@dirmaster.example.com#邮件的发送地址
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 eth0#HA的检测网络接口
virtual_router_id 51#主和备机的id必须一样,且在0~255
priority 100#主机的优先级,备机应该此值小点
advert_int 1#主备之间的通告时间间隔秒数
authentication {
auth_type PASS#设置验证类型
auth_pass 1111#设置验证密码
}
virtual_ipaddress {
192.168.2.100#VIP
}
}
virtual_server 192.168.2.100 80 {
delay_loop 4#每隔4秒查询realserver的状态
lb_algo rr#rr论叫算法
lb_kind DR#LVS的DR模式
# persistence_timeout 50 #保持会话使用的
protocol TCP
real_server 192.168.2.11 80 {
weight 1 #权重
TCP_CHECK { #realserver的状态检测设置部分
connect_timeout 3 #3秒无响应超时
nb_get_retry 3 #重试次数
delay_before_retry 3 #重试间隔
}
}
real_server 192.168.2.12 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}


改完配置文件就可以直接启动keepalived了,但有时还可能报错,

[root@dirmaster ~]# service keepalived start
 /etc/init.d/keepalived: Permission denied
 chmod a+x /etc/init.d/keepalived 就好了。
现象:




当http出现问题后的现象。