首页 > 代码库 > 负载均衡

负载均衡

  负载均衡(load balance)是分布式系统架构设计中必须考虑的因素之一。它通常指的是将请求/数据“均衡”的分摊给多个操作单元来执行,负载均衡的关键在于“均衡”。均衡不能狭义的理解为平均把工作分配给每一台服务器,每个服务器的承载能力各不相同,可能是因为硬件配置,网络宽带的差异,也有可能是因为某台服务器身兼数职。我们所说的负载均衡,主要希望可以让所有服务器都不要过载,并且最大程度的发挥作用。下面讲述一下负载均衡的目前技术。

一、http重定向

当http代理(比如浏览器)向web服务器请求某个url之后,web服务器可以通过http响应头信息中的location标记来返回一个新的url,这意味着http代理需要继续请求这个新的url,完成自动跳转。

缺点:

1.吞吐率限制

主站点服务器的吞吐率平均分配到了被转移的服务器,假设现在使用RR(Round Robin)调度策略(轮询算法),子服务器的最大吞吐率为1000reqs/s,那么主服务器需要达到3000reqs/s才能完全发挥三台服务器的作用,如果有100台服务器的话,那么主服务器的吞吐率可想而知的多大?相反如果现在主服务器的吞吐率是6000reqs/s,那么平均分配到子服务器的吞吐率为2000reqs/s,现在只有1000reqs/s,需要增加到6台服务器才能满足。

2.重定向的访问深度不同

有时候需要重定向到一个静态页面,有时候需要重定向到一个动态页面,实际服务器的负载差异是不可预知的,而主站服务器却一无所知,因此整站使用重定向方法做负载均衡不太好。我们需要权衡转移请求的开销和实际处理请求的开销,前者相对于后者越小,重定向的意义就越大。例如下载,你可以去很多镜像网站进行下载,发现基本下载都使用了location做了重定向。

二、DNS负载均衡

DNS负责提供域名解析服务,当访问某个站点的时候,DNS会先通过该站点域名的DNS服务器获得该域名指向的IP地址。在这一过程中,DNS完成了域名到IP的映射,同样这样的映射也可以是一对多的,这个时候DNS就充当了一个负载均衡的调度器,他就像http重定向策略一样,将访问请求分发到多台服务器上,但是他的实现机制完全不同。

使用dig命令查看百度的DNS设置

技术分享

baidu.com拥有四个A记录

相比于http重定向,基于DNS负载均衡完全节省了主站点,DNS已经充当了主站点的职能。但不同的是,同样作为调度器的DNS服务器是几乎不用担心性能的,因为DNS记录是会被用户的浏览器和互联网接入的服务商的各级DNS服务器缓存,只有缓存过期才会想DNS服务器重新请求解析,DNS服务器不存在http吞吐率的限制,理论上可以无限增加服务器的数量。

特点:

1.可以根据用户的IP来进行智能解析。DNS可以在所有可用的A记录中找到一台距离用户最近的服务器。

2.动态DNS:每次在IP地址变更时,及时更新DNS服务器。因为缓存,一定的延迟(立即生效大概15分钟)。

缺点:

1.没有用户能直接看到DNS解析到了哪一台服务器,给服务器的运维人员调试带来了不便。

2.策略的局限性。例如无法将http的上下文引入到调度策略中,前文介绍的http重定向负载均衡系统中,调度工作在http层面,它可以充分的理解http的请求根据站点的应用逻辑来设计调度策略,比如根据不同的url来进行合理的过滤和转移。

3.如果要根据实际服务器的负载差异来调整调度策略,那么需要DNS服务器在每次解析操作的时候分析各服务器的健康状态,这对DNS服务器来说,这种自定义开发存在较高的门槛,而且大部分的站点使用的是第三方的DNS服务器。

4.DNS记录缓存,各节点的DNS服务器不同程序的缓存会让你晕头转向。

总结:

DNS服务器并不能很好的完成负载均衡的分配工作,是否选择取决于你的需要。

三、反向代理负载均衡

几乎所有的web服务器都热衷于支持基于方向代理的负载均衡,它的核心工作就是转发http请求。相比于http重定向和DNS解析,反向代理扮演的就是中间人的角色,任何对于实际服务器的http请求都必须经过调度器,调度器必须等待实际服务器的HTTP响应,并将它反馈给用户。

特性:

1.调度策略丰富,可以为不同的服务器设置不同的权重,达到能者多劳的效果。

2.对反向代理服务器的并发处理能力要求高,因为他工作在HTTP层面。

3.反向代理服务器进行转发操作本身是需要一定开销的,比如创建线程,与后端服务器建立TCP连接,接收后端服务器的返回结果,分析http的头部信息、用户空间和内核空间的频繁切换等,虽然这部分时间并不长,但是当后端服务器处理请求的耗时特别短,转发的开销就显得尤为突出。例如请求静态文件更适合前面介绍的DNS负载均衡方式。

4.反向代理服务器可以监控后端服务器,比如系统负载,响应时间,是否可用,TCP链接数、流量等从而可以根据这些数据调整负载均衡的策略。

5.反向代理服务器可以让用户在一次会话周期内所有的请求始终转发在一台特定的后端服务器上(黏滞会话),这样的好处一是保持session本地访问,二是防止后端服务器的动态内容缓存的资源浪费。

四、LVS负载均衡

LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器,现在LVS是linux标准内核的一部分。

1.LVS-NAT(IP负载均衡)

因为反向代理工作在HTTP层,其本身的开销就已经严重的制约了可扩展性,从而限制了他的性能极限。NAT服务器工作在传输层,他可以修改发来的IP数据包,将数据包的目标地址修改为实际服务器地址。

从linux2.4内核开始,其内置的Neftilter模块在内核中维护着一些数据包过滤表,这些表包含了数据包过滤的规则。Linux提供了iptables来对过滤表进行插入、修改和删除等操作。Linux2.6内核中内置了IPVS模块,他的工作性质类似于Neftilter,不过他更专注于实现IP负载均衡。

技术分享

IPVS的管理工具是ipvsadm,它提供了基于命令行的配置界面,可以通过他快速实现负载均衡系统。

①打开调度器的数据包转发选项

echo 1 > /proc/sys/net/ipv4/ip_forward

②检查实际服务器是否将NAT服务器作为自己的默认网关,如果不是则添加。

route add default gw xx.xx.xx.xx

③使用ipvsadm配置

ipvsadm -A -t 111.11.11.11:80 -s rr  

 添加一台虚拟服务器,-t 后面是服务器的外网ip和端口,-s rr是指采用简单轮询的RR调度策略(这属于静态调度策略,除此之外,LVS还提供了系列的动态调度策略,比如最小连接(LC)、带权重的最小连接(WLC),最短期望时间延迟(SED)等)

ipvsadm -a -t 111.11.11.11:80 -r 10.10.120.210:8000 -m  

ipvsadm -a -t 111.11.11.11:80 -r 10.10.120.211:8000 -m  

添加两台实际服务器(不需要有外网ip),-r后面是实际服务器的内网ip和端口,-m表示采用NAT方式来转发数据包。

运行ipvs - L -n可以查看实际服务器的状态。

实验证明使用基于NAT的负载均衡系统可以将吞吐率提升到一个新的高度,几乎是反向代理的两倍,这归功于内核请求转发较低的开销。但是一旦请求内容太大,不论是反向代理还是NAT,负载均衡整体的吞吐率差距不大,这说明对于开销较大的内容,使用反向代理是值得考虑的。NAT负载均衡系统的瓶颈在于NAT服务器的网络带宽,包括内部网络和外部网络。如果不差钱可以花钱购买千兆交换机或者万兆交换机,甚至负载均衡设备。如果没钱可以使用基于NAT的集群和DNS混用,比如5个100Mbps出口宽带的集群,然后通过DNS来将用户请求均衡地指向这些集群,同时,你还可以利用DNS智能解析实现地域就近访问。这样的配置对于大多数业务是足够了,但是对于提供下载或视频等服务的大规模站点,NAT服务器还是不够出色。

技术分享

 

优点:

  • 对后端服务器的操作系统无要求
  • 只需要一个IP地址配置在调度器上,服务器组可以使用私有的IP
  • 支持端口映射缺点

缺点:

  • 请求和响应报文都需要经过调度器,伸缩能力有限
  • 要求服务器和调度器在同一个VLAN
  • 需要将服务器的默认网关指向调度器
  • 对于那些将IP地址或者端口号在报文数据中传送的网络服务,需要编写相应的应用模块来转换报文数据中的IP和端口号

2.LVS-DR(直接路由)

NAT是工作在网络分层的传输层(4层),而直接路由是工作在数据链路层(第二层),他通过修改数据包的MAC地址,将数据包转发到实际服务器,不同的是,实际服务器的响应数据包是直接发送给客户端的,不经过调度器。

 ①网络设置

这里假设一台负载均衡调度器,两台实际服务器,购买三个外网ip,一台机一个,三台机的默认网关需要相同,最后再设置同样的ip别名,这里假设别名为10.10.120.193。这样一来,将通过10.10.120.193这个IP别名来访问调度器,你可以将站点的域名指向这个IP别名。

②将ip别名添加到回环接口lo上

这是为了让实际服务器不要去寻找其他拥有这个IP别名的服务器,在实际服务器中运行:

技术分享

另外还要防止实际服务器响应来自网络中针对IP别名的ARP广播,为此还要执行:

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 "1" > /proc/sys/net/ipv4/conf/all/arp_announce

配置完了就可以使用ipvsadm配置LVS-DR集群了

ipvsadm -A -t 10.10.120.193:80 -s rr  

ipvsadm -a -t 10.10.120.193:80 -r 10.10.120.210:8000 -g  

ipvsadm -a -t 10.10.120.193:80 -r 10.10.120.211:8000 -g  

 -g 就意味着使用直接路由的方式转发数据包

LVS-DR 相较于LVS-NAT的最大优势在于LVS-DR不受调度器宽带的限制,例如假设三台服务器在WAN交换机出口宽带都限制为10Mbps,只要对于连接调度器和两台实际服务器的LAN交换机没有限速,那么,使用LVS-DR理论上可以达到20Mbps的最大出口宽带,因为它的实际服务器的响应数据包可以不经过调度器而直接发往用户端啊,所以它与调度器的出口宽带没有关系,只能自身的有关系。而如果使用LVS-NAT,集群只能最大使用10Mbps的宽带。所以,越是响应数据包远远超过请求数据包的服务,就越应该降低调度器转移请求的开销,也就越能提高整体的扩展能力,最终也就越依赖于WAN出口宽带。

总的来说,LVS-DR适合搭建可扩展的负载均衡系统,不论是Web服务器还是文件服务器,以及视频服务器,它都拥有出色的性能。前提是你必须为实际器购买一系列的合法IP地址。

技术分享

技术分享

优点:

  • 与LVS-TUN相比,没有IP隧道的开销,性能最好

缺点:

  • 要求调度器和服务器都有一块网卡连在同一物理网段(同一个VLAN)上
  • 要求服务器网络设备不做ARP广播响应,或者能将报文重定向到本地的SOCKET端口上
  • 服务器上直接绑定虚拟IP(Virtaul IP),风险很大
  • 不支持端口映射

 

3.LVS-TUN(IP隧道)

基于IP隧道的请求转发机制:将调度器收到的IP数据包封装在一个新的IP数据包中,转交给实际服务器,然后实际服务器的响应数据包可以直接到达用户端。目前Linux大多支持,可以用LVS来实现,称为LVS-TUN,与LVS-DR不同的是,实际服务器可以和调度器不在同一个WANt网段,调度器通过IP隧道技术来转发请求到实际服务器,所以实际服务器也必须拥有合法的IP地址。

总体来说,LVS-DR和LVS-TUN都适合响应和请求不对称的Web服务器,如何从它们中做出选择,取决于你的网络部署需要,因为LVS-TUN可以将实际服务器根据需要部署在不同的地域,并且根据就近访问的原则来转移请求,所以有类似这种需求的,就应该选择LVS-TUN。

技术分享

技术分享

优点:

  • 不需要调度应答报文,性能高
  • 服务器和调度器可以不再一个VLAN
  • 支持广域负载均衡

缺点:

  • 所有服务器必须支持“IP Tunneling”协议,要安装内核模块(比如IPIP等),配置复杂
  • 有建立IP隧道的开销
  • 服务器上直接绑定虚拟IP,风险很大
  • 服务器需要联通外网
  • 不支持端口映射

注释:

1.网络七层协议:从上到下分别是应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。

2.TCP/IP四层协议:从上到下分别是网络接口层、互连网络层、传输层、应用层。

负载均衡