lvs负载均衡技术-阿里云开发者社区

开发者社区> 开发与运维> 正文

lvs负载均衡技术

简介:

本文在参考誉天邹老师培训教程基础上,已做部分补充完善,大家阅读时有个思路即可。

 

lvs负载均衡技术

1.相关术语
什么是负载均衡?
在大型的网络应用中,使用多台服务器提供同一个服务是常有的事。平均分配每台服务器上的压力、将压力分散的方法就叫做负载均衡。

智能DNS轮询?
实现服务器流量的负载均衡,原理是“给网站访问者随机分配不同ip”

集群?
由2台或多台计算机连接在一起,共同执行任务的。
根据业务目标分为:HA(高可用)、LB(负载均衡)、HP(高性能)

HA:keepalived、heartbeat、rhcs
LB:lvs、nginx、haproxy、F5
HP:
www.zghpc.com/index/Downfile/infor_id/42


2.lvs负载均衡技术深究
2.1 lvs简介
linux虚拟服务器,由章文嵩博士发起的自由软件项目,现在lvs成为linux标准内核的一部分,直接编译到内核中了。
编译进内核的模块叫ipvs,管理工具叫ipvsadm,类似于iptables,netfiler编译进内核的模块,iptables是其一个管理工具;

如何查看内核是否编译指定模块?(查看/boot下的config文件)
cat config-2.6.18-194.el5 |grep -i ipvs

一个模块的功能是否被加进内核中,如何查看?
=y 在内核中已经编译成模块,并每次开机默认加载,如lsmod;
=m 在内核中已经编译成模块,默认不加载,有需要再加载,如nfs;
lsmod |grep nfs #查看nfs模块,默认是没有被加载的
modprobe nfs  #加载nfs模块


2.2 lvs的3种工作模式
dr、nat、tun

lvs-nat:
rs和ds必须在同一个网络,仅用于与ds通信;
ds接收所有数据包;
rs默认网关指向ds;
ds支持端口映射,即将客户端请求映射到rs的另一个端口;
支持任意平台os;
单一的ds是整个集群瓶颈;
扩展有限,DS将处理所有请求,压力大,扩展10个就不行了;

lvs-dr:
rs必须与ds在同一网络;
rs是公网IP地址;
ds接收的数据包,根据调度算法将数据包转发到rs;
rs不需要ds作为默认网关;
支持任意平台os;
可支持更多rs;
性能最佳,但必须要求近距离,如同一个机房,不能做异地分布,lvs-tun可解决;

lvs-tun:
dr和rs不必在同一个网络;
rip必须使用公网地址;
ds只处理进来的请求,不处理出去的请求;
ds不支持端口映射;
只能使用那些支持IP隧道协议的os做rs;
可实现基于网络的集群,脱离lvs-dr的rs之间的距离限制;

专线加密;
二层:在mac之外再加一层mac;
三层:源ip目标ip之外再加一层ip;
隧道目的:隐藏意图,通过转换(ip套ip)来隐藏目的;

现系统内核默认支持以下2个内核参数。
arp_ignore:定义对目标地址为本地IP的ARP询问不同的应答模式
0 - (默认值): 回应任何网络接口上对任何本地IP地址的arp查询请求
1 - 只回答目标IP地址是来访网络接口本地地址的ARP查询请求
2 -只回答目标IP地址是来访网络接口本地地址的ARP查询请求,且来访IP必须在该网络接口的子网段内
3 - 不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应
4-7 - 保留未使用
8 -不回应所有(本地地址)的arp查询 

arp_announce:对网络接口上本地IP地址发出的ARP回应作出相应级别的限制:
0 - (默认) 在任意网络接口(eth0,eth1,lo)上的任何本地地址
1 -尽量避免不在该网络接口子网段的本地地址做出arp回应,当发起ARP请求的源IP地址是被设置应该经由路由达到此网络接口的时候很有用,此时会检查来访IP是否为所有接口上的子网段内ip之一。如果该来访IP不属于各个网络接口上的子网段内,那么将采用级别2的方式来进行处理。
2 - 对查询目标使用最适当的本地地址。在此模式下将忽略这个IP数据包的源地址并尝试选择与能与该地址通信的本地地址,首要是选择所有的网络接口的子网中外出访问子网中包含该目标IP地址的本地地址, 如果没有合适的地址被发现,将选择当前的发送网络接口或其他的有可能接受到该ARP回应的网络接口来进行发送。

lvs-dr模式工作原理的常见问题
(1)lvs-dr如何处理请求报文的,会修改IP包内容吗?不会修改IP包的内容
lvs-dr本身不会关心IP层以上的信息,即使是端口号也是tcp/ip协议栈去判断是否正确,lvs-dr本身主要做这么几个事:
1)接收client的请求,根据设定的负载均衡算法选取一台realserver的ip;
2)以选取的这个ip对应的mac地址作为目标mac,然后重新将IP包封装成帧转发给这台RS;
3)在hash table中记录连接信息。

vs/dr做的事情很少,也很简单,所以它的效率很高,不比硬件负载均衡设备差多少。
数据包、数据帧的大致流向是这样的:client --> VS --> RS --> client

(2)RealServer为什么要在lo接口上配置VIP?在出口网卡上配置VIP可以吗?
既然要让RS能够处理目标地址为vip的IP包,首先必须要让RS能接收到这个包。在lo上配置vip能够完成接收包并将结果返回client。

不可以将VIP设置在出口网卡上,否则会响应客户端的arp request,造成client/gateway arp table紊乱,以至于整个load balance都不能正常工作。

(3)RealServer为什么要抑制arp帧?
lvs-dr在同一个网络,且RS和DS都配有vip地址,当客户端请求VIP时,谁去响应?这时候只允许DS接收arp请求,RS就要抑制arp请求。(RS内核参数arp_ignore实现)

DS不知道RS上有vip地址的,DS只负责把arp请求分配给RS,RS接收到数据包后,打开数据包发现目标ip在lo:0上,就给lo:0,回应的时候也希望通过lo:0接口,这样就可以避免RS直接响应客户端,更好地屏蔽RS。

上一问题中已经作了说明,这里结合具体实施部署时说明:
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
这两条是可以不用的,因为arp对逻辑接口没有意义。

echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
如果RS的外部网络接口是eth0,那么真正要执行的是:
echo "1" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/eth0/arp_announce
在此建议把上面两条也加到脚本里,因为万一系统里上面两条默认的值不是0,那可能会出问题。

arp_ignore:定义对目标地址为本地IP的ARP询问不同的应答模式;
别人的arp请求,我不接收,我不响应别人的arp,我不接收别人;
arp_announce:对网络接口上本地IP地址发出的ARP回应作出相应级别的限制。
别人访问我这个接口,我不用这个接口响应别人,我主动去广播。

(4)lvs-dr load balancer(director)与RS为什么要在同一网段中?
从第一个问题中应该明白lvs-dr是如何将请求转发给RS的?它是在数据链路层来实现的,所以director必须和RS在同一网段里面。

(5)为什么director上eth0接口除了VIP另外还要配一个ip(即DIP)?
如果是用了keepalived等工具做HA或者Load Balance,则在健康检查时需要用到DIP,否则没有存在的实际意义。

(6)lvs-dr ip_forward需要开启吗?
不需要。因为director跟realserver是同一个网段,无需开启转发。

(7)director的vip的netmask一定要是255.255.255.255吗?
lvs-dr里,director的vip的netmask 没必要设置为255.255.255.255,也不需要。
route add -host $VIP dev eth0:0
director的vip本来就是要像正常的ip地址一样对外通告的,不要搞得这么特殊.

参考LVS-DR工作原理图文详解
http://www.cnblogs.com/czh-liyu/archive/2011/11/29/2267963.html


2.3 lvs的4种静态调度算法
所谓静态就是请求进来后,按照某种调度算法,将请求分给后端真实服务器,不关心后端是否有活动连接,后端忙不忙跟我没有关系,我只负责分配请求;
动态就是判断后端真实服务器的繁忙程度,再分配请求;

(1)轮询调度rr
将外部请求按顺序轮流分配到集群中的真实服务器,均等对待每一台服务器,不管服务器的连接数和系统负载;

类似DNS轮询;
优先级或权值没有意义;

问题:一服务器很繁忙,请求被调度过来,另一服务器很空闲,没有请求调度。

(2)加权轮询wrr
根据真实服务器的不同处理能力来调度访问请求,保证性能强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态调整其权值。

设定优先级或权值,性能好的权值高,处理请求多,数值越大,权重越高;
与ha中的权重有区别,wrr设为1:10,

问题:性能好的服务器处理很繁忙,请求还是调度过来,不会将请求调度给性能差些的空闲服务器。

(3)目标地址散列(目标哈希)dh
以请求的目标ip地址,作为散列键从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

客户端请求第一次调度给a服务器,下次访问仍然调度给a服务器,可产生缓存。

(4)源地址散列sh
以请求的源ip地址,作为散列键从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。


2.4 lvs的6种动态调度算法
(1)最少链接lc
通过lc动态地将请求调度到已建立的连接数最少的服务器上。集群系统中的真实服务器具有相近的系统性能,采用lc调度算法可以较好的负载均衡。

调度器会计算真实服务器的活动连接数和非活动连接数的总和,
判断连接数的个数,

服务器开销=活动连接数*256+非活动连接数,值小的,调度器就分配请求给谁。

(2)加权最少链接wlc
对于集群系统中服务器性能差异较大的情况下,调度器采用wlc可以优化负载均衡性能,具有最高权值的服务器将承受较大比例的活动连接负载。调度器可以自动询问真实服务器的负载情况,并动态调整其权值。

默认的调度算法,最优秀的调度算法,目前绝大多数都采用此算法;
服务器开销=(活动连接数*256+非活动连接数)/权重,值小的,调度器就分配请求给谁。

(3)最短的期望延迟sed
在wlc基础上进行优化;
只考虑活动连接数;
服务器开销=(活动连接数+1)*256/权重,值小的,调度器就分配请求给谁。
为了避免活动连接数都为0,请求分配给谁?

(4)最少队列调度ng
在wlc基础上进行优化;
无需队列,若一台真实服务器的连接数为0,就直接分配过去,不需要进行sed运算。
只考虑活动连接数;
在sed运算时,活动连接数都为0,a权重为1,b权重为10,则10个请求都分给B?

(5)基于局部的最少链接(lblc)
dh的动态实现,对目标ip地址的负载均衡,用于cache集群系统。
以请求的目标ip地址,找出该目标ip地址最近使用的服务器,若该服务器是可用的且未超载,将请求发送到该服务器;
的原则选出一个可用的服务器,将请求发送过去。

(6)带复制的基于局部的最少链接(lblcr)
lblc是维护从一个目标IP地址到一台服务器的映射;
lblcr是维护从一个目标IP地址到一组服务器的映射;

以请求的目标IP地址找出该目标IP地址对应的服务器组,按最少链接lc原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若超载,则按lc原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。

2.5 lvs-nat实例配置:
拓扑:
Director:eth0 10.124.0.1(dip) eth1:172.16.0.1(vip) 开启路由转发
Realserver1: eth0 10.124.0.21 gw 10.124.0.1 开启httpd
Realserver2: eth0 10.124.0.22 gw 10.124.0.1 开启httpd
client:172.16.0.11

#添加集群服务
ipvsadm -A -t 172.16.0.1:80 -s rr
ipvsadm -L -n
#为集群服务添加主机,t即tcp;m即nat,dr即r;w即权重
ipvsadm -a -t 172.16.0.1:80 -r 10.124.0.21 -m -w 1
ipvsadm -a -t 172.16.0.1:80 -r 10.124.0.22 -m -w 2
#保存配置
service ipvsadm save
#修改调度算法
ipvsadm -E -t 172.16.0.1:80 -s wrr

2.6 lvs-dr实例配置:
拓扑:
DS:eth0 10.124.0.1(dip)
RS1: eth0 10.124.0.21  开启httpd
RS2: eth0 10.124.0.22  开启httpd
client:10.124.0.252

#配置DS子接口
ifconfig eth0:1 10.124.0.100 broadcast 10.124.0.100 netmask 255.255.255.255 up
#配置路由,回应走eth0:1
route add -host 10.124.0.100 dev eth0:1
route -n

#需要安装ipvsadm
#DS配置集群和调度主机,-g默认的dr模式,最终显示为route
ipvsadm -A -t 10.124.0.100:80 -s wlc
ipvsadm -a -t 10.124.0.100:80 -g -r 10.124.0.21 -w 1
ipvsadm -a -t 10.124.0.100:80 -g -r 10.124.0.22 -w 2
ipvsadm -L -n


#配置RS,安装httpd
#设置内核参数,不接收别的arp广播,不广播自己的mac地址
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

#配置lo:0,ip地址不是给某个网卡的,是属于这个服务器上。
ifconfig lo:0 10.124.0.100 broadcast 10.124.0.100 netmask 255.255.255.255 up
#配置路由,回应客户端走lo:0。因为不指定的话,eth0也可能回应客户端。
route add -host 10.124.0.100 dev lo:0


单一DS挂掉,怎么办?lvs+keepalived
#两台DS上安装keepalived
yum -y install kernel-devel gcc openssl-devel
tar -zxvf keepalived-1.1.19.tar.gz
cd keepalived-1.1.19
./configure  --sysconf=/etc --with-kernel-dir=/usr/src/kernels/2.6.18-8.el5-i686
make && make install
ln -s /usr/local/sbin/keepalived  /sbin/

在编译选项中,“--sysconf”指定了Keepalived配置文件的安装路径,即路径为/etc/Keepalived/Keepalived.conf,“--with-kernel-dir”这个参数必须指定,否则就找不到ipvs,启动不起来,但这个参数并不是要把Keepalived编译进内核,而是指定使用内核源码里面的头文件,就是include目录。如果要使用LVS时,才需要用到此参数,否则是不需要的。

#配置keepalived文件
vim /etc/Keepalived/Keepalived.conf
global_defs {
  router_id LVS_MASTER  #backup节点为LVS_BACKUP
}

vrrp_instance VI_1 {
  state MASTER  #backup节点为BACKUP
  interface eth0
  virtual_router_id 51
  priority 100  #backup节点为80
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  virtual_ipaddress {
    192.168.10.100
  }
}

virtual_server 192.168.10.100 80 {
  delay_loop 6
  lb_algo rr
  lb_kind DR
  net_mask 255.255.255.0
  persistence_timeout 50
  protocol TCP

  real_server 192.168.10.3 80 {
    weight 1
    TCP_CHECK {
      connect_timeout 10
      nb_get_retry 3
      delay_before_retry 3
      connect_port 80
    } 
  }

  real_server 192.168.10.4 80 {
    weight 1
    TCP_CHECK {
      connect_timeout 10
      nb_get_retry 3
      delay_before_retry 3
      connect_port 80
    } 
  }
}

#启动keepalived服务,并添加到开机启动
/etc/init.d/keepalived start
chkconfig keepalived on


#realserver设置
cat /etc/init.d/realserver.sh
#!/bin/bash

WEB_VIP=192.168.10.100
./etc/rc.d/init.d/functions

case "$1" in
start)
       ifconfig lo:0 $WEB_VIP netmask 255.255.255.255 broadcast $WEB_VIP
       /sbin/route add -host $WEB_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)
       ifconfig lo:0 down
       route del $WEB_VIP >/dev/null 2>&1
       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
       echo "RealServer Stoped"
       ;;
*)
# Invalid entry.
        echo "Usage: $0 {start|stop}"
        exit 1
esac
exit 0

#设置执行权限,并启动服务,添加开机启动
chmod +x /etc/init.d/realserver.sh
/etc/init.d/realserver.sh start
ln -s /etc/init.d/realserver.sh /etc/rc.d/rc3.d/S99realserver.sh
ln -s /etc/init.d/realserver.sh /etc/rc.d/rc5.d/S99realserver.sh

(2013年7月14日更新v1.0)

本文转自自由心行博客51CTO博客,原文链接http://blog.51cto.com/xiaojiang2008/1248456如需转载请自行联系原作者


xiaojiang

版权声明:本文首发在云栖社区,遵循云栖社区版权声明:本文内容由互联网用户自发贡献,版权归用户作者所有,云栖社区不为本文内容承担相关法律责任。云栖社区已升级为阿里云开发者社区。如果您发现本文中有涉嫌抄袭的内容,欢迎发送邮件至:developer2020@service.aliyun.com 进行举报,并提供相关证据,一经查实,阿里云开发者社区将协助删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章