仅需这一篇,吃透负载均衡

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介:

在对分布式系统的「高可用」有了一个初步了解之后,我们也认识到「负载均衡」是「高可用」的核心所在。那么,本篇文章我们将通过图文并茂的方式,来描述出每一种负载均衡策略的完整样貌。

一、负载均衡是什么

由一个独立的统一入口来收敛流量,再做二次分发的过程就是「负载均衡」,它的本质和「分布式系统」一样,是「分治」。

如果大家习惯了开车的时候用一些导航软件,我们会发现,导航软件的推荐路线方案会有一个数量的上限,比如3条、5条。

其实,它也起到了一个类似「负载均衡」的作用,因为如果只能取Top3的通畅路线,自然拥堵严重的路线就无法推荐给你了,使得车流的压力被分摊到了相对空闲的路线上。

在软件系统中也是一样的道理,为了避免流量分摊不均,造成局部节点负载过大(如CPU吃紧等),所以引入一个独立的统一入口来做类似上面的“导航”的工作。但是,软件系统中的「负载均衡」与导航的不同在于,导航是一个柔性策略,最终还是需要使用者做选择,而前者则不同。

怎么均衡的背后是策略在起作用,而策略的背后是由某些算法或者说逻辑来组成的。比如,导航中的算法属于「路径规划」范畴,在这个范畴内又细分为「静态路径规划」和「动态路径规划」,并且,在不同的分支下还有各种具体计算的算法实现,如Dijikstra、A*等。

同样的,在软件系统中的负载均衡,也有很多算法或者说逻辑在支撑着这些策略,巧的是也有静态和动态之分。

二、常用负载均衡策略图解

下面来罗列一下日常工作中最常见的5种策略。

1、轮询

fb460a64dfccfe47a83291683bdee4ce55430640

这是最常用也最简单的策略,平均分配,人人都有、一人一次。大致的代码如下:

int globalIndex = 0; //注意是全局变量,不是局部变量。

try

{

return servers[globalIndex];

}

finally

{

globalIndex++;

if (globalIndex == 3)

globalIndex = 0;

}

2、加权轮询
fe82595df247c758fc7170959f8c43c8123b7033

在轮询的基础上,增加了一个权重的概念。权重是一个泛化后的概念,可以用任意方式来体现,本质上是能者多劳的思想。比如,可以根据宿主的性能差异配置不同的权重。大致的代码如下:

int matchedIndex = -1;

int total = 0;

for (int i = 0; i < servers.Length; i++)

{

servers[i].cur_weight += servers[i].weight;//①每次循环的时候做自增(步长=权重值)

total += servers[i].weight;//②将每个节点的权重值累加到汇总值中

if (matchedIndex == -1 || servers[matchedIndex].cur_weight < servers[i].cur_weight) //③如果 当前节点的自增数 > 当前待返回节点的自增数,则覆盖。

{

matchedIndex = i;

}

}

servers[matchedIndex].cur_weight -= total;//④被选取的节点减去②的汇总值,以降低下一次被选举时的初始权重值。

return servers[matchedIndex];

这段代码的过程如下图的表格。“()”中的数字就是自增数,代码中的cur_weight。

fa5d68b8363fc07e1a1d2ff0c8f0656cef35edb4

值得注意的是,加权轮询本身还有不同的实现方式,虽说最终的比例都是2:1:2。

但是在请求送达的先后顺序上可以有所不同。比如「5-4,3,2-1」和上面的案例相比,最终比例是一样的,但是效果不同,「5-4,3,2-1」更容易产生并发问题,导致服务端拥塞,且这个问题随着权重数字越大越严重。例如,10:5:3的结果是「18-17-16-15-14-13-12-11-10-9,8-7-6-5-4,3-2-1」。

3、最少连接数

9a85b82e4bcf54740915dd8c1e45123430a0c434

这是一种根据实时的负载情况,进行动态负载均衡的方式。维护好活动中的连接数量,然后取最小的返回即可。大致的代码如下:

var matchedServer = servers.orderBy(e => e.active_conns).first();

matchedServer.active_conns += 1;

return matchedServer;

//在连接关闭时还需对active_conns做减1的动作。

4、最快响应
1f2a4a80cba28d7a8fb7306ae5c6f30bab9c42b3

这也是一种动态负载均衡策略,它的本质是根据每个节点对过去一段时间内的响应情况来分配,响应越快分配的越多。具体的运作方式也有很多,上图的这种可以理解为:将最近一段时间的请求耗时的平均值记录下来,结合前面的「加权轮询」来处理,所以等价于2:1:3的加权轮询。

题外话:一般来说,同机房下的延迟基本没什么差异,响应时间的差异主要在服务的处理能力上。

如果在跨地域(例:浙江->上海,还是浙江->北京)的一些请求处理中运用,大多数情况会使用定时「ping」的方式来获取延迟情况,因为是OSI的L3转发,数据更干净,准确性更高。

5、Hash法

c4695785c004bd6d32ce66960ca1d11d5775984d

Hash法的负载均衡与之前的几种不同在于,它的结果是由客户端决定的。通过客户端带来的某个标识经过一个标准化的散列函数进行打散分摊。

上图中的散列函数运用的是最简单粗暴的「取余法」。

题外话:散列函数除了取余之外,还有诸如「变基」、「折叠」、「平方取中法」等等,此处不做展开,有兴趣的小伙伴可自行查阅资料。

另外,被求余的参数其实可以是任意的,只要最终转化成一个整数参与运算即可。最常用的应该是用来源IP地址作为参数,这样可以确保相同的客户端请求尽可能落在同一台服务器上。

三、常用负载均衡策略优缺点和适用场景

我们知道,没有完美的事物,负载均衡策略也是一样。上面列举的这些最常用的策略也有各自的优缺点和适用场景,我稍作了整理,如下:

a034e17838fa1669121c0db5b5d0eeaae2a9b886

这些负载均衡算法之所以常用也是因为简单,想要更优的效果,必然就需要更高的复杂度。比如,可以将简单的策略组合使用、或者通过更多维度的数据采样来综合评估、甚至是基于进行数据挖掘后的预测算法来做。

四、用健康探测来保障高可用

不管是什么样的策略,都难免会遇到机器故障或者程序故障的情况。所以要确保负载均衡能更好的起到效果,还需要结合一些「健康探测」机制。定时的去探测服务端是不是还能连上,响应是不是超出预期的慢。

如果节点属于“不可用”的状态的话,需要将这个节点临时从待选取列表中移除,以提高可用性。一般常用的「健康探测」方式有3种。

1、HTTP探测

使用Get/Post的方式请求服务端的某个固定的URL,判断返回的内容是否符合预期。一般使用Http状态码、Response中的内容来判断。

2、TCP探测

基于TCP的三次握手机制来探测指定的IP+端口。最佳实践可以借鉴阿里云的SLB机制,如下图:

c04fc932e9601fd473f4beebfb8abba80ed4e693

图片来源于阿里云,版权归原作者所有

值得注意的是,为了尽早释放连接,在三次握手结束后立马跟上RST来中断TCP连接。

3、UDP探测

可能有部分应用使用的是UDP协议。在此协议下可以通过报文来进行探测指定的IP+端口。最佳实践同样可以借鉴阿里云的SLB机制,如下图:

968939b0fa294f54087f2d9bc35d9597227deef1

图片来源于阿里云,版权归原作者所有

结果的判定方式是:在服务端没有返回任何信息的情况下,默认正常状态;否则会返回一个ICMP的报错信息。

五、结语

用一句话来概括负载均衡的本质是:

将请求或者说流量,以期望的规则分摊到多个操作单元上进行执行。

通过它可以实现横向扩展(Scale Out),将冗余的作用发挥为「高可用」。另外,还可以物尽其用,提升资源使用率。


原文发布时间为:2018-11-26

本文作者:Zachary

本文来自云栖社区合作伙伴“DBAplus社群”,了解相关信息可以关注“DBAplus社群”。

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
2月前
|
负载均衡 监控 算法
每个程序员都应该知道的 6 种负载均衡算法
每个程序员都应该知道的 6 种负载均衡算法
223 2
|
域名解析 负载均衡 网络协议
软件测试面试题:负载均衡如何实现?
软件测试面试题:负载均衡如何实现?
134 0
|
负载均衡 算法 Java
负载均衡(Ribbon)-原来如此简单
负载均衡(Ribbon)-原来如此简单
232 0
负载均衡(Ribbon)-原来如此简单
|
负载均衡 前端开发 JavaScript
负载均衡设计|学习笔记
快速学习负载均衡设计
负载均衡设计|学习笔记
|
负载均衡 算法 安全
面试官:负载均衡的算法你了解不?
上一篇文章我讲了关于负载均衡的三种算法,轮询法,随机法,最小连接法,这三种负载均衡的算法,但是关于负载均衡还有其他的算法,我们也需要你去看,而且在面试的过程中,很有可能是会问到的呦。 对于要实现高性能集群,选择好负载均衡器很重要,同时针对不同的业务场景选择合适的负载均衡算法也是非常重要的。之前已经罗列出几个了,接下来在说剩下的几个算法,
|
弹性计算 负载均衡 数据安全/隐私保护
DLB负载均衡实践
在高并发的情况下,经常会导致服务器响应速度慢,严重的情况会直接导致服务器停止服务。此时,会导致企业的业务中断,影响客户的正常访问。 本场景通过使用阿里云负载均衡SLB以及对负载均衡SLB后端服务器ECS的权重进行修改,可以快速解决上述的问题。
DLB负载均衡实践
|
负载均衡 算法 网络协议
仅需这一篇,带你吃透「负载均衡」!
一、「负载均衡」是什么 正如题图所示的这样,由一个独立的统一入口来收敛流量,再做二次分发的过程就是「负载均衡」,它的本质和「分布式系统」一样,是「分治」。
1359 0
|
负载均衡 弹性计算
【实操】配置负载均衡
帮您快速掌握如何配置负载均衡。
2107 0
|
负载均衡 算法 网络协议
搞懂分布式技术10:LVS实现负载均衡的原理与实践
文末对一些概念进行了讲解,比如vip,loopback回环地址,以及iptables做了一些介绍。可以参见文末内容。 浅析负载均衡及LVS实现 原创: fireflyc 写程序的康德 2017-09-19 负载均衡 负载均衡(Load Balance,缩写LB)是一种网络技术,它在多个备选资源中做资源分配,以达到选择最优。