一、LVS概念
LVS(Linux Virtual Server):Linux 虚拟服务器
LVS是个负载均衡设备,它不提供任何服务,用户请求到这里的时候,它是将客户需求转发至后端真正提供服务的服务,所以说后端的服务称作real server。LVS分为两段,前一段称为ipvsadm(管理集群服务的命令行工具),后面一段叫做ipvs(内核模块)【提示:LVS和iptables不能同时使用】。
二、LVS类型
LB(Load Balancing):负载均衡集群
特性:为了增加能力能力
HA(High Availability):高可用集群
特性:提供服务的可用性(一年在线时间达到99.999%才行)
计算方法:在线时间/(在线时间/故障处理时间)
HP([HPC]High Performance):高性能集群
特性:提供服务的性能
三、LVS组成结构(负载均衡实现方案)
基于DNS域名轮流解析的方法
基于客户端调度访问的方法
基于应用层系统负载的调度方法
基于IP地址的调度方法
其中基于IP的负载调度算法中,IP负载均衡技术是执行效率最高的
四、LVS十种调度算法
1、静态调度:
①rr(Round Robin):轮询调度,轮叫调度
轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。【提示:这里是不考虑每台服务器的处理能力】
②wrr:weight,加权(以权重之间的比例实现在各主机之间进行调度)
由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。
③sh:source hashing,源地址散列。主要实现会话绑定,能够将此前建立的session信息保留了
源地址散列调度算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的并且没有超负荷,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。它的算法流程与目标地址散列调度算法的基本相似,除了将请求的目标IP地址换成请求的源IP地址,所以这里不一个一个叙述。
④Dh:Destination hashing:目标地址散列。把同一个IP地址的请求,发送给同一个server。
目标地址散列调度算法也是针对目标IP地址的负载均衡,它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
2、动态调度
①lc(Least-Connection):最少连接
最少连接调度算法是把新的连接请求分配到当前连接数最小的服务器,最小连接调度是一种动态调度短算法,它通过服务器当前所活跃的连接数来估计服务器的负载均衡,调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1,当连接中止或超时,其连接数减一,在系统实现时,我们也引入当服务器的权值为0时,表示该服务器不可用而不被调度。
简单算法:active*256+inactive(谁的小,挑谁)
②wlc(Weighted Least-Connection Scheduling):加权最少连接。
加权最小连接调度算法是最小连接调度的超集,各个服务器用相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权限,加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。
简单算法:(active*256+inactive)/weight【(活动的连接数+1)/除以权重】(谁的小,挑谁)
③sed(Shortest Expected Delay):最短期望延迟
基于wlc算法
简单算法:(active+1)*256/weight 【(活动的连接数+1)*256/除以权重】
④nq(never queue):永不排队(改进的sed)
无需队列,如果有台realserver的连接数=0就直接分配过去,不需要在进行sed运算。
⑤LBLC(Locality-Based Least Connection):基于局部性的最少连接
基于局部性的最少连接算法是针对请求报文的目标IP地址的负载均衡调度,不签主要用于Cache集群系统,因为Cache集群中客户请求报文的布标IP地址是变化的,这里假设任何后端服务器都可以处理任何请求,算法的设计目标在服务器的负载基本平衡的情况下,将相同的目标IP地址的请求调度到同一个台服务器,来提高个太服务器的访问局部性和主存Cache命中率,从而调整整个集群系统的处理能力。
基于局部性的最少连接调度算法根据请求的目标IP地址找出该目标IP地址最近使用的RealServer,若该Real Server是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
⑥LBLCR(Locality-Based Least Connections withReplication):带复制的基于局部性最少链接
带复制的基于局部性最少链接调度算法也是针对目标IP地址的负载均衡,该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
五、IPVS实现负载均衡的方法
NAT:地址转换(类似于DNAT)
1、集群点跟director必须工作在同一个IP的网络中
2、RIP通常是私有地址,仅用于各集群节点间的的通信
3、director位于client和real server之间,并负责处理进出的所有通道。
4、realserver必须将网关执行DIP
5、director支持端口映射
6、realserver可以使用任何类型的操作系统(os)
7、较大规模应用场景中,director易成为系统瓶颈
DR:直接路由(及用于作为源地址)
1、各集群节点跟director必须在同一个物理网络中;
2、RIP可以使用公网地址,实现便携的远程管理和监控;
3、director仅负责处理入站请求,形影报文则有realserver直接发往客户端
4、realserver不能将网关指向DIP,而是直接指向前端网关;
5、director不支持端口映射
6、大多数操作系统能够用在realserver
7、director能够处理更多的realserver
TUN:隧道
1、集群节点可以跨越Internet
2、RIP必须是公网地址
3、director仅负责处理入站请求,形影报文则有realserver直接发往客户端
4、realserver网关不能指向director
5、只有咫尺隧道功能的OS才能用于realserver
6、不支持端口映射
六、ipvsadm常用命令
ipvsadm:
1、管理集群服务
添加:-A -t|u|f service-address [-sscheduler]
-t:tcp协议的集群服务
-u:udp协议的集群
-f:FWM:防火墙标记
修改:-E
删除:-D
-D -t|u|f service-address
例如:# ipvsadm -A -t 172.16.100.1:80 -s rr
2、管理集群服务中的RS
添加:-a -t|u|f service-address -rserver-address [-g|i|m] [-w weight]
-t|u|f service-address:事先定义好的某集群服务
-r server-address:某RS的地址,在NAT模型中,可以使用IP:PORT事先端口映射
[-g|i|m]:LVS类型
-g:DR
-I:TUN
-m:NAT
[-w weight]:定义服务器权重
3、修改:-e
4、删除:-d -t|u|f service-address -r server-address
例如:#ipvsadm -a -t 172.16.100.1:80 -r192.168.10.8 -m
例如:#ipvsadm-a -t 172.16.100.1:80 -r 192.168.10.9 -m
5、查看
-L|l[options]
-n:数字格式显示主机地址和端口号
--stats:统计信息
--rate:速率
--timeout:显示tcp、tcpfin和udp会话的超时时间值
--daemon
--sort:跟协议、地址、端口进行排序,默认为升序
-c:显示当前ipvs连接状况
6、删除所有集群服务:
-C:清空ipvs规则
7、保存规则
-S:(用输出重定向进行保存)
格式:#ipvsadm -s >/path/to/somefile
8、载入此前的规则:
-R
格式:#ipvsadm -R </path/to/somefile
动态反馈负载均衡算法考虑服务器的实时负载和响应情况,不断调整服务器间处理请求的比例,来避免有些服务器超载时依然收到大量请求,从而提高整个系统的吞吐率。图4.1显示了该算法的工作环境,在负载调度器上运行Monitor Daemon进程,Monitor Daemon来监视和收集各个服务器的负载信息。Monitor Daemon可根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值,若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中,而在内核中连接调度一般采用加权轮叫调度算法或者加权最小连接调度算法。
当客户通过TCP连接访问网络访问时,服务所需的时间和所要消耗的计算资源是千差万别的,它依赖于很多因素。例如,它依赖于请求的服务类型、当前网络带宽的情况、以及当前服务器资源利用的情况。一些负载比较重的请求需要进行计算密集的查询、数据库访问、很长响应数据流;而负载比较轻的请求往往只需要读一个HTML页面或者进行很简单的计算。
请求处理时间的千差万别可能会导致服务器利用的倾斜(Skew),即服务器间的负载不平衡。例如,有一个WEB页面有A、B、C和D文件,其中D是大图像文件,浏览器需要建立四个连接来取这些文件。当多个用户通过浏览器同时访问该页面时,最极端的情况是所有D文件的请求被发到同一台服务器。所以说,有可能存在这样情况,有些服务器已经超负荷运行,而其他服务器基本是闲置着。同时,有些服务器已经忙不过来,有很长的请求队列,还不断地收到新的请求。反过来说,这会导致客户长时间的等待,觉得系统的服务质量差。
简单连接调度
简单连接调度可能会使得服务器倾斜的发生。在上面的例子中,若采用轮叫调度算法,且集群中正好有四台服务器,必有一台服务器总是收到D文件的请求。这种调度策略会导致整个系统资源的低利用率,因为有些资源被用尽导致客户的长时间等待,而其他资源空闲着。
实际TCP/IP流量的特征
文献说明网络流量是呈波浪型发生的,在一段较长时间的小流量后,会有一段大流量的访问,然后是小流量,这样跟波浪一样周期性地发生。文献揭示在WAN和LAN上网络流量存在自相似的特征,在WEB访问流也存在自相似性。这就需要一个动态反馈机制,利用服务器组的状态来应对访问流的自相似性。
TCP/IP流量的特征通俗地说是有许多短事务和一些长事务组成,而长事务的工作量在整个工作量占有较高的比例。所以,我们要设计一种负载均衡算法,来避免长事务的请求总被分配到一些机器上,而是尽可能将带有毛刺(Burst)的分布分割成相对较均匀的分布。
我们提出基于动态反馈负载均衡机制,来控制新连接的分配,从而控制各个服务器的负载。例如,在IPVS调度器的内核中使用加权轮叫调度(Weighted Round-Robin Scheduling)算法来调度新的请求连接;在负载调度器的用户空间中运行Monitor Daemon。Monitor Daemon定时地监视和收集各个服务器的负载信息,根据多个负载信息算出一个综合负载值。Monitor Daemon将各个服务器的综合负载值和当前权值算出一组新的权值。当综合负载值表示服务器比较忙时,新算出的权值会比其当前权值要小,这样新分配到该服务器的请求数就会少一些。当综合负载值表示服务器处于低利用率时,新算出的权值会比其当前权值要大,来增加新分配到该服务器的请求数。若新权值和当前权值的差值大于设定的阀值,Monitor Daemon将该服务器的权值设置到内核中的IPVS调度中。过了一定的时间间隔(如2秒钟),Monitor Daemon再查询各个服务器的情况,并相应调整服务器的权值;这样周期性地进行。可以说,这是一个负反馈机制,使得服务器保持较好的利用率。
在加权轮叫调度算法中,当服务器的权值为零,已建立的连接会继续得到该服务器的服务,而新的连接不会分配到该服务器。系统管理员可以将一台服务器的权值设置为零,使得该服务器安静下来,当已有的连接都结束后,他可以将该服务器切出,对其进行维护。维护工作对系统都是不可少的,比如硬件升级和软件更新等,零权值使得服务器安静的功能很主要。所以,在动态反馈负载均衡机制中我们要保证该功能,当服务器的权值为零时,我们不对服务器的权值进行调整。
在计算综合负载时,我们主要使用两大类负载信息:输入指标和服务器指标。输入指标是在调度器上收集到的,而服务器指标是在服务器上的各种负载信息。我们用综合负载来反映服务器当前的比较确切负载情况,对于不同的应用,会有不同的负载情况,这里我们引入各个负载信息的系数,来表示各个负载信息在综合负载中轻重。系统管理员根据不同应用的需求,调整各个负载信息的系数。另外,系统管理员设置收集负载信息的时间间隔。
输入指标主要是在单位时间内服务器收到新连接数与平均连接数的比例,它是在调度器上收集到的,所以这个指标是对服务器负载情况的一个估计值。在调度器上有各个服务器收到连接数的计数器,对于服务器Si,可以得到分别在时间T1和T2时的计数器值Ci1和Ci2,计算出在时间间隔T2-T1内服务器 Si收到新连接数Ni = Ci2 - Ci1。这样,得到一组服务器在时间间隔T2-T1内服务器Si收到新连接数{Ni},服务器Si的输入指标INPUTi为其新连接数与n台服务器收到平均连接数的比值,其公式为
服务器指标主要记录服务器各种负载信息,如服务器当前CPU负载LOADi、服务器当前磁盘使用情况Di、当前内存利用情况Mi和当前进程数目 Pi。有两种方法可以获得这些信息;一是在所有的服务器上运行着SNMP(Simple Network Management Protocol)服务进程,而在调度器上的Monitor Daemon通过SNMP向各个服务器查询获得这些信息;二是在服务器上实现和运行收集信息的Agent,由Agent定时地向Monitor Daemon报告负载信息。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零,不会有新的连接再被分配到该服务器;若在下一次服务器有响应,再对服务器的权值进行调整。再对这些数据进行处理,使其落在[0, ∞)的区间内,1表示负载正好,大于1表示服务器超载,小于1表示服务器处于低负载状态。获得调整后的数据有DISKi、MEMORYi和 PROCESSi。
另一个重要的服务器指标是服务器所提供服务的响应时间,它能比较好地反映服务器上请求等待队列的长度和请求的处理时间。调度器上的Monitor Daemon作为客户访问服务器所提供的服务,测得其响应时间。例如,测试从WEB服务器取一个HTML页面的响应延时,Monitor Daemon只要发送一个“GET /”请求到每个服务器,然后记录响应时间。若服务器在设定的时间间隔内没有响应,Monitor Daemon认为服务器是不可达的,将服务器在调度器中的权值设置为零。同样,我们对响应时间进行如上调整,得到RESPONSEi。
这里,我们引入一组可以动态调整的系数Ri来表示各个负载参数的重要程度,其中ΣRi = 1。综合负载可以通过以下公式计算出:
例如,在WEB服务器集群中,我们采用以下系数{0.1, 0.3, 0.1, 0.1, 0.1, 0.3},认为服务器的CPU负载和请求响应时间较其他参数重要一些。若当前的系数Ri不能很好地反映应用的负载,系统管理员可以对系数不断地修正,直到找到贴近当前应用的一组系数。
另外,关于查询时间间隔的设置,虽然很短的间隔可以更确切地反映各个服务器的负载,但是很频繁地查询(如1秒钟几次)会给调度器和服务器带来一定的负载,如频繁执行的Monitor Daemon在调度器会有一定的开销,同样频繁地查询服务器指标会服务器带来一定的开销。所以,这里要有个折衷(Tradeoff),我们一般建议将时间间隔设置在5到20秒之间。
当服务器投入集群系统中使用时,系统管理员对服务器都设定一个初始权值DEFAULT_WEIGHTi,在内核的IPVS调度中也先使用这个权值。然后,随着服务器负载的变化,对权值进行调整。为了避免权值变成一个很大的值,我们对权值的范围作一个限制[DEFAULT_WEIGHTi, SCALE*DEFAULT_WEIGHTi],SCALE是可以调整的,它的缺省值为10。
Monitor Daemon周期性地运行,若DEFAULT_WEIGHTi不为零,则查询该服务器的各负载参数,并计算出综合负载值AGGREGATE_LOADi。我们引入以下权值计算公式,根据服务器的综合负载值调整其权值。
在公式中,0.95是我们想要达到的系统利用率,A是一个可调整的系数(缺省值为5)。当综合负载值为0.95时,服务器权值不变;当综合负载值大于0.95时,权值变小;当综合负载值小于0.95时,权值变大。若新权值大于SCALE*DEFAULT_WEIGHTi,我们将新权值设为 SCALE*DEFAULT_WEIGHTi。若新权值与当前权值的差异超过设定的阀值,则将新权值设置到内核中的IPVS调度参数中,否则避免打断 IPVS调度的开销。我们可以看出这是一个负反馈公式,会使得权值调整到一个稳定点,如系统达到理想利用率时,权值是不变的。
在实际使用中,若发现所有服务器的权值都小于他们的DEFAULT_WEIGHT,则说明整个服务器集群处于超载状态,这时需要加入新的服务器结点到集群中来处理部分负载;反之,若所有服务器的权值都接近于SCALE*DEFAULT_WEIGHT,则说明当前系统的负载都比较轻。
我们在RedHat集群管理工具Piranha[6]中实现了一个简单的动态反馈负载均衡算法。在综合负载上,它只考虑服务器的CPU负载(Load Average),使用以下公式进行权值调整:
服务器权值调整区间为[DEFAULT_WEIGHTi, 10*DEFAULT_WEIGHTi],A为DEFAULT_WEIGHTi /2,而权值调整的阀值为DEFAULT_WEIGHTi /4。1是所想要达到的系统利用率。Piranha每隔20秒查询各台服务器的CPU负载,进行权值计算和调整。
分类: C/C++
负载均衡的基本算法,主要有以下几种(参考F5产品):
性能调优社区dynatrace在其博客中分享了客户案例,电商网站在假日客流峰值期间数次崩溃,经过SQL优化和调整负载均衡算法解决了相关问题.首先要分析执行最慢的数据库语句,并做性能优化,比如增加索引等。同时也优化了连接池大小来满足高峰时刻的需求。然后,企业把负载均衡器的算法从Round-Robin改为了Least-Busy。
相关文章:
电商网站的宕机案例分析
ASP.NET Session State Partitioning
ASP.NET Session State Partitioning using State Server Load Balancing
解析nginx负载均衡
Round Robin Scheduling
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; namespace LoadBalancer { public class LoadBalance { /// <summary> /// 锁对象 /// </summary> private static readonly object locker = new object(); /// <summary> /// 服务器权重列表 /// </summary> private static List<int> weightList = new List<int>(); /// <summary> /// 当前索引 /// </summary> private static int currentIndex; /// <summary> /// 当前权重 /// </summary> private static int currentWeight; private static int maxWeight; /// <summary> /// 最大公约数 /// </summary> private static int gcd; static LoadBalance() { currentIndex = -1; currentWeight = 0; //获取服务器权重列表,从配置文件 weightList = GetWeightList(); maxWeight = GetMaxWeight(weightList); gcd = GetMaxGCD(weightList); } private static List<int> GetWeightList() { List<int> list = new List<int>(); list.Add(3); list.Add(1); list.Add(1); list.Add(4); list.Add(1); list.Add(7); return list; } [MethodImpl(MethodImplOptions.Synchronized)] public static int Start() { lock (locker) { int? iWeight = RoundRobin(); if (iWeight != null) { return (int)iWeight; } return weightList[0]; } } /// <summary> /// 获取最大公约数 /// </summary> /// <param name="list">要查找的int集合</param> /// <returns>返回集合中所有数的最大公约数</returns> private static int GetMaxGCD(List<int> list) { list.Sort(new WeightCompare()); int iMinWeight = weightList[0]; int gcd = 1; for (int i = 1; i < iMinWeight; i++) { bool isFound = true; foreach (int iWeight in list) { if (iWeight % i != 0) { isFound = false; break; } } if (isFound) gcd = i; } return gcd; } /// <summary> /// 获取服务器权重集合中的最大权重 /// </summary> /// <param name="list"></param> /// <returns></returns> private static int GetMaxWeight(List<int> list) { int iMaxWeight = 0; foreach (int i in list) { if (iMaxWeight < i) iMaxWeight = i; } return iMaxWeight; } private static int? RoundRobin() { while (true) { currentIndex = (currentIndex + 1) % weightList.Count; if (0 == currentIndex) { currentWeight = currentWeight - gcd; if (0 >= currentWeight) { currentWeight = maxWeight; if (currentWeight == 0) return null; } } if (weightList[currentIndex] >= currentWeight) { return weightList[currentIndex]; } } } } public class WeightCompare : IComparer<int> { public int Compare(int x, int y) { return x - y; } } }
编者按:在CSDN云计算频道日前所做的文章《响应高达6秒 用户揭露Heroku私自修改路由造成高支出》中,网友们认为这是“因随机调度+Rails的单线程处理导致延迟增加的负载均衡失败的案例”。但在负载均衡测试时就能发现问题并妥善解决的成功经验有没有?在随后的微博中,支付宝的@Leverly评论:“去年双11前的压测OB就发现了存在严重的随机访问导致负载不均问题,还好通过加权算法很好的解决了。” 引发了我们的关注,于是有了本文。重点是淘宝在“双十一”背后,OceanBase分布式系统负载均衡的经验分享。
以下为正文:
云计算所具备的低成本、高性能、高可用性、高可扩展性等特点与互联网应用日益面临的挑战不谋而合,成为近年来互联网领域的热门话题。作为一名技术人员不难理解在云计算的底层架构中,分布式存储是不可或缺的重要组成部分。国外知名的互联网公司如Google、Amazon、Facebook、Microsoft、Yahoo等都推出了各自的分布式存储系统,在国内OceanBase是淘宝自主研发的一个支持海量数据的高性能分布式数据库系统,实现了数千亿条记录、数百TB数据上的跨行跨表事务[1]。
在分布式系统中存在着著名的“短板理论”[2],一个集群如果出现了负载不均衡问题,那么负载最大的机器往往将成为影响系统整体表现的瓶颈和短板。为了避免这种情况的发生,需要动态负载均衡机制,以达到实时的最大化资源利用率,从而提升系统整体的吞吐。
本文将结合OceanBase的实际应用和大家分享一个去年淘宝双十一前期的准备工作中遇到负载均衡相关案例,抛砖引玉,期望对大家的工作有所启发。
OceanBase是一个具有自治功能的分布式存储系统,由中心节点RootServer、静态数据节点ChunkServer、动态数据节点UpdateServer以及数据合并节点MergeServer四个Server构成[1],如图1所示。
图1 OceanBase 架构图
在一个集群中,Tablet的多个副本分别存储在不同的ChunkServer,每个ChunkServer负责一部分Tablet分片数据,MergeServer和ChunkServer一般会一起部署。
对于淘宝的大部分应用而言,“双十一”就是一年一度的一次线上压测。伴随流量不断刷新着历史新高,对每个系统的可扩展性提出了很大的挑战。为了迎战双十一各产品线对有可能成为瓶颈部分的流量进行预估和扩容成为刻不容缓的任务。在本文要分享的案例中,应用方根据历史数据预估读请求的访问峰值为7w QPS,约为平时的5-6倍,合计每天支持56亿次的读请求。当时OceanBase集群部署规模是36台服务器,存储总数据量为200亿行记录,每天支持24亿次的读请求。
当前集群的读取性能远不能满足需求,我们首先进行了一次扩容,上线了10台Chunkserver/Mergeserver服务器。由于OceanBase本身具有比较强的可扩展性,为集群加机器是一件非常简单的操作。中心节点Rootserver在新机器注册上线后,会启动Rebalance功能以Tablet为单位对静态数据进行数据迁移,见下图的示意,最终达到所有ChunkServer上数据分片的均衡分布。
表 1. 某Table的Tablet列表
图2.1 Tablet在三台ChunkServer上的分布
图2.2加入一台机器Tablet迁移后的分布
扩容完成后引入线上流量回放机制进行压力测试,以验证当前集群的性能是否可以满足应用的双十一需求。我们使用了10台服务器,共2000-4000个线程并发回放线上读流量对集群进行压测,很快发现集群整体的QPS在达到4万左右后,压测客户端出现大量超时现象,平均响应延迟已经超过阈值100ms,即使不断调整压力,系统的整体QPS也没有任何增大。此时观察整个集群机器的负载状态发现只有极个别服务器的负载超高,是其他机器的4倍左右,其他机器基本处于空闲状态,CPU、网络、磁盘IO都凸现了严重的不均衡问题。
负载不均衡导致了整体的吞吐取决于负载最高的那台Server,这正是前文提到的典型 “短板理论”问题。
客户端连接到OceanBase之后一次读请求的读流程如下图所示:
图3 客户端到OceanBase的读流程图
OceanBase的读请求流程看起来如此复杂,实际上第1步和第3步中Client与RootServer以及MergeServer与RootServer的两次交互会利用缓存机制来避免,即提高了效率,同时也极大降低了RootServer的负载。
分析以上的流程可知,在第2步客户端选择MergeServer时如果调度不均衡会导致某台MergeServer机器过载;在第4步MergeServer把子请求发送到数据所在的ChunkServer时,由于每个tablet会有多个副本,选择副本的策略如果不均衡也会造成ChunkServer机器过载。由于集群部署会在同一台机器会同时启动ChunkServer和MergeServer,无法简单区分过载的模块。通过查看OceanBase内部各模块的提供的监控信息比如QPS、Cache命中率、磁盘IO数量等,发现负载不均问题是由第二个调度问题引发,即MergeServer对ChunkServer的访问出现了不均衡导致了部分ChunkServer的过载。
ChunkServer是存储静态Tablet分片数据的节点,分析其负载不均的原因包含如下可能:
通过对RootServer管理的所有tablet数据分片所在位置信息Metadata进行统计,我们发现各个ChunkServer上的tablet数据量差异不大,这同时也说明扩容加入新的Server之后,集群的Rebalance是有效的(后来我们在其他应用的集群也发现了存在数据不均衡问题,本文暂不解释)。
尽管排除了数据不均衡问题,流量不均衡又存在如下的几种可能性:
经过如上的分析至少已经确定ChunkServer流量不均衡问题和步骤4紧密相关的,而目前所采用的tablet副本选择的策略是随机法。一般而言随机化的负载均衡策略简单、高效、无状态,结合业务场景的特点进行分析,热点数据所占的比例并不会太高,把ChunkServer上的Tablet按照访问次数进行统计也发现并没有超乎想象的“大热点”,基本服从正太分布。
可见热点Tablet虽访问频率稍高对负载的贡献率相对较大,但是热点tablet的占比很低,相反所有非热点tablet对负载的贡献率总和还是很高的,这种情况就好比“长尾效应”[3]。
如果把热点ChunkServer上非热点Tablet的访问调度到其他Server,是可以缓解流量不均问题的,因此我们设计了新的负载均衡算法为:以实时统计的ChunkServer上所有tablet的访问次数为Ticket,每次对Tablet的读请求会选择副本中得票率最低的ChunkServer。
同时考虑到流量不均衡的第二个原因是请求的差异较大问题,ChunkServer对外提供的接口分为Get和Scan两种,Scan是扫描一个范围的所有行数据,Get是获取指定一行数据,因此两种访问方式的次数需要划分赋予不同的权重(α,β)参与最终Ticket的运算:
除此之外,简单的区分两种访问模式还是远远不够的,不同的Scan占用的资源也是存在较大差异的,引入平均响应时间(avg_time)这个重要因素也是十分必要的:
负载均衡算法要求具有自适应性和强的实时性,一方面新的访问要实时累积参与下次的负载均衡的调度,另一方面历史权重数据则需要根据统计周期进行非线性的衰减(y 衰减因子),减少对实时性的影响:
采用新的算法后,很好的缓解了负载不均衡的问题,整体负载提升了1倍,整体QPS吞吐提升到了8w。
负载均衡问题是老生常谈的问题,解决不好就会出现“短板效应”,更甚至引发分布式系统中的连锁反应即“雪崩”,从而演化成系统的灾难。负载均衡的算法也层出不穷,有的出于成本最优,有的是为了最小延迟,有的则是最大化系统吞吐,目的不同算法自然各异,不存在包治百病的良方,并不是越复杂的算法越有效[4],要综合考虑算法所需数据获取的Overhead,更多的是遵循“简单实用”的法则,根据业务场景进行分析和尝试。
正是这种灵活性的策略,对我们的系统设计提出了新的需求,要有一定的机制来监控和验证问题:比如可以实时获取系统运行的各种内部状态和数据,允许选择不同负载均衡算法进行试验等。
Update1:看到楼下网友专业方面的提问,@Leverly 已经进行了回复。有更多交流,不妨直接讨论。共享:)!
3月2日Update2:图2.2已更换(原图右边显示不完全,应为“A,E,G,H,I")。
参考文献
1.OceanBase : http://oceanbase.taobao.org/
2.Buckets effect: http://www.baike.com/wiki/%E6%9C%A8%E6%A1%B6%E7%90%86%E8%AE%BA
3.Long Tail: http://en.wikipedia.org/wiki/The_long_tail
4.http://www.cs.usask.ca/faculty/eager/loadsharing.pdf
欢迎 @CSDN云计算微博参与讨论,了解更多云信息。
负载均衡的发展基础就是负载均衡算法。那么针对不同的服务器我们也会采用不同的负载均衡算法,因为他们所具备的和要求的功能各不相同。那么我们现在就来详细了解一下这方面的知识。希望能让大家从中得到需要的东西。
服务器负载均衡算法有很多(持续性的和非持续性的),包括轮循算法、最少连接算法、响应时间算法、散列算法、最少连接失误算法,链路带宽算法等等。
此外实际服务器(RealServer)可以被分配不同的加权值来调整被分配的流量。比如性能高的大型服务器可配置较大的加权值,而为性能较低的小型服务器设置较小的加权值。为了避免服务器因过载而崩溃,可为实际服务器指定最大连接阈值来避免该服务器过载。任何服务器可被指定为另一台服务器的备份服务器或溢出服务器,从而进一步保证了应用可用性。
非持续性算法(Non-Persistent):
一个客户端的不同的请求可能被分配到一个实际服务组中的不同的实服务器上进行处理。
主要有轮循算法、最少连接算法、响应速度算法等。
轮循算法(RoundRobin):
说明:每一次来自网络的请求轮流分配给内部中的每台服务器,从1至N然后重新开始。
举例:此种负载均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况;
最少连接算法(LeastConnection):
说明:客户端的每一次请求服务在服务器停留的时间都可能会有较大的差异,随着工作时间的加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,这样的结果并不会达到真正的负载均衡。最少连接数均衡算法对内部中有负载的每一台服务器都有一个数据记录,记录的内容是当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。
举例:此种负载均衡算法适合长时间处理的请求服务。
响应速度算法(ResponseTime):
说明:负载均衡设备对内部各服务器发出一个探测请求(例如Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。
举例:此种负载均衡算法能较好地反映服务器的当前运行状态,但最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。
持续性算法(Persistent):
从一个特定的客户端发出的请求都被分配到一个实服务组中的同一个实服务器上进行处理。
主要包括的负载均衡算法有:
A.基于IP的算法
Persistent IP(pi):基于用户IP地址来选择服务器。
Hash IP(hi):基于用户IP地址的HASH值,来选择服务器
Consistent Hash IP(chi):基于列表IP来选择服务器
B.基于报头/请求的算法
HashHeader(hh):基于用户请求报中HTTP报头来选择服务器;
PersistentHostname(ph):基于用户请求报中HTTP报头的Hostname的HASH值,来选择服务器;
PersistentURL(pu):基于对URITag和值的静态对应关系来选择服务器。
SSLSessionID(sslsid):基于SSL会话ID来选择服务器。
C.基于Cookie的负载均衡算法
PersistentCookie(pc):选择服务器基于用户请求包用CookieName/Value的静态对应关系;
HashCookie(hc):选择服务器基于用户请求包用CookieName/Value的Hash值对应关系;
InsertCookie(ic):选择服务器基于负载均衡器向服务器响应包中插入Cookie;
Re-writeCookie(rc):选择服务器基于负载均衡器向服务器响应包中重写Cookie值。(必须为重写指定Cookie值的偏移量)
感觉作者对此文章写得很好,为了方便以后自己能够常看,故此搬到这里来。
原文出处:http://network.51cto.com/art/201005/197952.htm