预计阅读本页时间:-
7.1.3 以LVS作为负载均衡器
LVS全称为Linux Virtual Server,是章文嵩博士(现淘宝网基础核心软件研发负责人)主持的自由项目。它是一个负载均衡/高可用性集群,主要针对大业务量的网络应用(如新闻服务、网上银行、电子商务等)。LVS建立在一个主控服务器(通常为双机)及若干真实服务器(Real-Server)所组成的集群之上。Real-Server负责实际提供服务,主控服务器根据指定的调度算法对Real-Server进行控制。而集群的结构对于用户来说是透明的,客户端只与单个的IP(集群系统的虚拟IP)进行通信,也就是说从客户端的视角来看,这里只存在单个服务器。Real-Server可以提供众多服务,如FTP、HTTP、DNS、Telnet、SMTP,现在比较流行的还有将其用于MySQL集群等。主控服务器负责对Real-Server进行控制。客户端在向LVS发出服务请求时,负载均衡器会通过特定的调度算法来指定由某个Real-Server来应答请求,而客户端只与负载均衡的IP(即虚拟的VIP)进行通信,LVS技术现在已经是一种成熟的负载均衡技术了,更多详情请大家参考官方文档。
1.LVS的新模式FULLNAT简介
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
在大规模的网络应用中,比如在淘宝的业务中,官方LVS的3种模式(即大家熟悉的DR、NAT及TUNNEL模式)都满足不了需求,原因有以下3点:
·3种转发模式的部署成本都比较高。
·和商用的负载均衡相比,LVS没有DDoS攻击防御功能。
·主备部署模式使得性能无法扩展。
下面来展开描述一下第一点,即LVS转发模式的部署成本高的缺点。
·DR的不足:必须要求LVS跟后端所有的REPLY放在同一个VLAN里。当然有人会提出来分几个区,每个区布一个LVS,但一个区的VM资源没有了,就只能用其他区的VM,而用户需要将这些VM挂到同一个VIP下,这是无法实现的。
·NAT的不足:NAT最主要的问题就是配置处理很复杂。以前在购买商业设备的时候,我们需要在交换机上配置策略路由,OUT方向的策略路由;因为,我们在工作中会考虑部署多套负载均衡方案,如果选择默认路由就只能实现一套负载均衡方案。
·TUNNEL的不足:隧道的问题主要也是配置较复杂,Real-Server需要加载一个IP模块,同时进行一些配置。
针对上述问题,相应的解决方法就是采用新转发模式FULLNAT,实现LVS-RealServer间跨VLAN通信,并且IN/OUT流都经过LVS。
针对第二点,官方LVS缺少DDoS攻击防御模块的缺点,解决方法是:采用SYNPROXY(SYNFlood攻击防御模块)和其他TCP FLAG DDoS攻击防御策略。
针对第三点,性能无法线性扩展的缺点,解决方法是:采用Cluster部署模式。
LVS在大规模网络环境中应用的更多详细资料请参考http://blog.aliyun.com/1750 。
2.算法简介
选定了转发方式后,采用哪种调度算法将决定整个负载均衡的性能表现。不同的算法适用于不同的应用场合,有时可能需要针对特殊场合,自行设计调度算法。每个负载均衡器都有自己独有的算法,下面跟大家介绍下LVS/HAProxy/Nginx常见的算法。
首先是LVS的常见算法。
(1)轮叫调度(Round Robin)
调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。任何形式的负载均衡器(包括硬件或软件级别的)都带有基本的轮叫功能(也叫轮询功能)。
(2)加权轮叫(Weighted Round Robin)
调度器通过“加权轮叫”调度算法根据真实服务器的不同处理能力来调度访问请求。这样就可以保证处理能力强的服务器能够处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
(3)最少链接(Least Connections)
调度器通过“最少链接”调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用“最少链接”调度算法可以较好地均衡负载。
(4)加权最少链接(Weighted Least Connections)
在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少链接”调度算法优化负载均衡的性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
(5)基于局部性的最少链接(Locality-Based Least Connections,LBLC)
“基于局部性的最少链接”调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,则将请求发送到该服务器上;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器上。
(6)带复制的基于局部性的最少链接(Locality-Based Least Connections with Replication)
“带复制的基于局部性的最少链接”调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护的是从一个目标IP地址到一组服务器的映射,而LBLC算法维护的是从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最少链接”原则从服务器组中选出一台服务器,若服务器没有超载,则将请求发送到该服务器;若服务器超载,则按“最少链接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,若该服务器组有一段时间没有被修改,则将最忙的服务器从服务器组中删除,以降低复制的程度。
(7)目标地址散列(Destination IP Hashing)
“目标地址散列”调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表中找出对应的服务器,若该服务器是可用的且未超载,则将请求发送到该服务器,否则返回空。
(8)源地址散列(Source IP Hashing)
“源地址散列”调度算法根据请求的源IP地址,作为散列键从静态分配的散列表中找出对应的服务器,若该服务器是可用的且未超载,则将请求发送到该服务器,否则返回空。
(9)源IP端口散列(Source IP Port Hashing)
通过Hash函数将来自同一个源IP地址和源端口号的请求映射到后端的同一台服务器上,该算法适用于需要保证来自同一用户同一业务的请求被分发到同一台服务器的场景。
(10)随机(Random)
随机地将请求分发到不同的服务器上,从统计学的角度来看,调度的结果为各台服务器平均分担用户的连接请求,该算法适用于集群中各机器性能相当而且无明显优劣差异的场景。
下面来看看HAProxy的常见算法。
HAProxy的算法现在也越来越多了,具体有如下8种。
·roundrobin:表示简单的轮询,这个不用多说,负载均衡基本都具备这一算法。
·static-rr:每个服务器根据权重轮流使用,类似roundrobin,但它是静态的,这就意味着运行时修改权限是无效的。另外,它对服务器的数量没有限制。
·leastconn:连接数最少的服务器优先接收连接。leastconn建议用于长会话服务,例如LDAP、SQL、TSE等,而不适合于短会话协议,如HTTP。该算法是动态的,对于实例启动慢的服务器权重会在运行中动态调整。
·source:对请求源IP地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个客户端IP地址总是访问同一个服务器。如果哈希的结果随可用服务器数量的变化而变化,那么客户端会定向到不同的服务器。该算法一般用于不能插入Cookie的TCP模式。它还可以用于在广域网上为拒绝使用会话Cookie的客户端提供最有效的粘连。该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化进行调整。
·URI:表示根据请求的URI地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个URI地址总是访问同一个服务器。一般用于代理提供缓存服务的机器,以最大限度地提高缓存的命中率。该算法只能用于HTTP后端。该算法一般用于后端节点机器是缓存服务器的场景,它默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化进行调整。
·url_param:表示根据URL的参数来调度,用于将同一个用户的信息都发送到同一个后端服务器。在HTTP GET请求的查询串中查找中指定的URL参数,基本上可以锁定使用特制的URL到特定的负载均衡器节点的要求,该算法一般用于将同一个用户的信息发送到同一个后端服务器。该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化进行调整。
·hdr(name):在每个HTTP请求中查找HTTP头,然后算法根据HTTP请求头来锁定每一次HTTP请求。如果缺少头或头没有任何值,则用roundrobin代替。该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化进行调整。
·rdp-cookie(name):查询每个进来的TCP请求并哈希RDP cookie,该机制用于退化的持久模式,可以使同一个用户或同一个会话ID总是发送给同一台服务器。如果没有Cookie,则使用roundrobin算法代替。该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化进行调整。
最后是Nginx的常见算法。
(1)轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器宕机,则会跳过该服务器分配至下一个监控的服务器。并且它无须记录当前所有连接的状态,所以它是一种无状态调度。
(2)weight
在轮询的基础上加上权重,weight和访问比率成正比,即用于表明后端服务器的性能好坏,这种情况特别适合后端服务器性能不一致的工作场景。
(3)ip_hash
每个请求按访问IP的哈希结果进行分配,当新的请求到达时,先将其客户端IP通过哈希算法进行计算得出一个值,随后的请求客户端IP的哈希值只要相同,就会被分配到同一台后端服务器上,该调度算法可以解决Session的问题,但有时会导致分配不均即无法保证负载均衡。
(4)fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
(5)url_hash(第三方)
按访问URL的哈希结果来分配请求,使每个URL定向到同一个后端服务器,后端服务器作为缓存时比较有效。
(6)Tengine增加的一致性哈希算法
这种算法应该是借鉴了目前最流行的一致性哈希算法思路。它的具体做法是:将每个Server虚拟成N个节点,均匀分布到哈希环上,每次请求时,根据配置的参数计算出一个哈希值,在哈希环上查找离这个哈希值最近的虚拟节点,对应的Server作为该次请求的后端机器,这样做的好处是如果动态增加了机器,或者某台Web机器宕机,对整个集群的影响会最小。
了解这些算法的原理能够在特定的应用场合选择最适合的调度算法,从而尽可能地保持Real Server的最佳利用性。当然也可以自行开发算法,不过这已超出本文范围,请参考有关算法原理的资料。