必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。

admin 4个月前 (06-01) 科技 40 0

2020 年 5 月 15 日,Dubbo 公布 2.7.7 release 版本。其中有这么一个 Features

新增一个负载平衡计谋。

熟悉我的老读者一定是知道的,Dubbo 的负载平衡我都写过专门的文章,对每个负载平衡算法举行了源码的解读,还分享了自己调试历程中的一些骚操作。

新的负载平衡出来了,那必须的得解读一波。

先看一下提交纪录:

https://github.com/chickenlj/incubator-dubbo/comMit/6d2ba7ec7b5a1cb7971143d4262d0a1bfc826d45

负载平衡是基于 SPI 实现的,我们看到对应的文件中多了一个名为 shortestrespoNSe 的 key。

这个,就是新增的负载平衡计谋了。看名字,你也知道了这个计谋的名称就叫:最短响应。

以是停止 2.7.7 版本,官方提供了五种负载平衡算法了,他们划分是:

  1. ConsistentHashLoadBalance 一致性哈希负载平衡
  2. LeastActiveLoadBalance 最小活跃数负载平衡
  3. RandomLoadBalance 加权随机负载平衡
  4. RoundRobinLoadBalance 加权轮询负载平衡
  5. ShortestResponseLoadBalance 最短响应时间负载平衡

前面四种我已经在之前的文章中举行了详细的剖析。有的读者反馈说想看合辑,以是我会在这篇文章中把之前文章也整合进来。

以是,需要稀奇强调一下的是,这篇文章聚集了之前写的三篇负载平衡的文章。看完最短响应时间负载平衡这一部门后,若是你看过我之前的那三篇文章,你可以温故而知新,也可以直接拉到文末看看我推荐的一个流动,然后点个赞再走。若是你没有看过那三篇,这篇文章若是你细看,一定有许多收获,以后谈起负载平衡的时刻若数家珍,然则一定需要看异常异常长的时间,做好心理准备。

我已经预感到了,这篇文章妥妥的会跨越 2 万字。属于硬核劝退文章,想想就畏惧。

最短响应时间负载平衡

首先,我们看一下这个类上的注解,先有个整体的认知。

org.apache.dubbo.rPC.cluster.loadbalance.ShortestResponseLoadBalance

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第1张

我来翻译一下是什么意思:

  1. 从多个服务提供者中选择出挪用乐成的且响应时间最短的服务提供者,由于知足这样条件的服务提供者有可能有多个。以是当选择出多个服务提供者后要凭据他们的权重做剖析。
  2. 然则若是只选择出来了一个,直接用选出来这个。
  3. 若是真的有多个,看它们的权重是否一样,若是不一样,则走加权随机算法的逻辑。
  4. 若是它们的权重是一样的,则随机挪用一个。

再配个图,就好明了了,可以先不管图片中的标号:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第2张有了上面的整体观点的铺垫了,接下来剖析源码的时刻就简朴了。

源码一共就 66 行,我把它分为 5 个片断去逐一剖析。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第3张

这里一到五的标号,对应上面流程图中的标号。我们一个个的说。

标号为①的部门

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第4张

这一部门是界说并初始化一些参数,为接下来的代码服务的,翻译一下每个参数对应的注释:

length 参数:服务提供者的数目。

shortestResponse 参数:所有服务提供者的估量最短响应时间。(这个地方我以为注释形貌的不太准确,看后面的代码可以知道这只是一个零时变量,在循环中存储当前最短响应时间是若干。)

shortCount 参数:具有相同最短响应时间的服务提供者个数,初始化为 0。

shortestIndexes 参数:数组内里放的是具有相同最短响应时间的服务提供者的下标。

weights 参数:每一个服务提供者的权重。

totalWeight 参数:多个具有相同最短响应时间的服务提供者对应的预热(预热这个点照样挺主要的,在下面讲最小活跃数负载平衡的时刻有详细说明)权重之和。

firstWeight 参数:第一个具有最短响应时间的服务提供者的权重。

sameWeight 参数:多个知足条件的提供者的权重是否一致。

标号为②的部门

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第5张

这一部门代码的要害,就在上面框起来的部门。而框起来的部门,最要害的地方,就在于第一行。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第6张

获取挪用乐成的平均时间。

乐成挪用的平均时间怎么算的?

挪用乐成的请求数总数对应的总耗时 / 挪用乐成的请求数总数 = 乐成挪用的平均时间。

以是,在下面这个方式中,首先获取到了挪用乐成的请求数总数:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第7张

这个 succeeded 参数是怎么来的呢?

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第8张

谜底就是:总的请求数减去请求失败的数目,就是请求乐成的总数!

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第9张

那么为什么不能直接获取请求乐成的总数呢?

别问,问就是没有这个选项啊。你看,在 RpcStatus 内里没有这个参数呀。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第10张

请求乐成的总数我们有了,接下来乐成总耗时怎么拿到的呢?

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第11张

谜底就是:总的请求时间减去请求失败的总时间,就是请求乐成的总耗时!

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第12张那么为什么不能直接获取请求乐成的总耗时呢?

别问,问就是......

我们看一下 RpcStatus 中的这几个参数是在那里维护的:

org.apache.dubbo.rpc.RpcStatus#enDCount(org.apache.dubbo.rpc.RpcStatus, long, boolean)

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第13张其中的第二个入参是本次请求挪用时长,第三个入参是本次挪用是否乐成。

详细的方式不必细说了吧,已经显而易见了。

再回去看框起来的那三行代码:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第14张

  1. 第一行获取到了该服务提供者乐成请求的平均耗时。
  2. 第二行获取的是该服务提供者的活跃数,也就是聚积的请求数。
  3. 第三行获取的就是若是当前这个请求发给这个服务提供者预计需要守候的时间。乘以 active 的缘故原由是由于它需要排在聚积的请求的后面嘛。

这里,我们就获取到了若是选择当前循环中的服务提供者的预计守候时间是多长。

后面的代码怎么写?

固然是出来一个更短的就把这个踢出去呀,或者出来一个一样长时间的就纪录一下,接着去 pk 权重了。

以是,接下来 shortestIndexes 参数和 weights 参数就排上用场了:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第15张

另外,多说一句的,它内里有这样的一行注释:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第16张

和 LeastActiveLoadBalance 负载平衡计谋一致,我给你截图对比一下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第17张可以看到,确实是异常的相似,只是一个是判断谁的响应时间短,一个是判断谁的活跃数低。

标号为③的地方

标号为③的地方是这样的:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第18张

内里参数的寄义我们都知道了,以是,标号为③的地方的寄义就很好注释了:经由选择后只有一个服务提供者知足条件。以是,直接使用这个服务提供者。

标号为④的地方

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第19张

这个地方我就不睁开讲了(后面的加权随机负载平衡那一小节有详细说明),熟悉的同伙一眼就看出来这是加权随机负载平衡的写法了。

不信?我给你对比一下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第20张

你看,是不是一模一样的。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第21张

标号为⑤的地方

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第22张

一行代码,没啥说的。就是从多个知足条件的且权重一样的服务提供者中随机选择一个。

若是一定要多说一句的话,我截个图吧:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第23张可以看到,这行代码在最短响应时间、加权随机、最小活跃数负载平衡计谋中都泛起了,且都在最后一行。

好了,到这里最短响应时间负载平衡计谋就讲完了,你再回过头去看那张流程图,会发现实在流程异常的清晰,完全可以凭据代码结构画出流程图。一个是说明这个算法是真的不庞大,另一个是说明好的代码会语言。

优雅

你知道 Dubbo 加入这个新的负载平衡算法提交了几个文件吗?

四个文件,其中还包罗两个测试文件:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第24张

这里就是计谋模式和 SPI 的利益。对原有的负载平衡计谋没有任何侵略性。只需要根据规则扩展设置文件,实现对应接口即可。

这是什么?

这就是值得学习优雅!

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第25张那我们优雅的进入下一议题。

最小活跃数负载平衡

这一小节所示源码,没有稀奇标注的地方均为 2.6.0 版本。

为什么没有用停止现在(我那时写这段文章的时刻是2019年12月01日)的最新的版本号 2.7.4.1 呢?由于 2.6.0 这个版本内里有两个 bug 。从 bug 讲起来,印象加倍深刻。

最后会对 2.6.0/2.6.5/2.7.4.1 版本举行对比,通过对比学习,加深印象。

我这里弥补一句啊,仅仅半年的时间,版本号就从 2.7.4.1 到了 2.7.7。其中还包罗一个 2.7.5 这样的大版本。

以是另有人说 Dubbo 不够活跃?(几年前的文章现在另有人在发。)

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第26张对吧,我们不打骂,我们摆事实,聊数据嘛。

Demo 准备

我看源码的习惯是先搞个 Demo 把调试环境搭起来。然后带着疑问去抽丝剥茧的 Debug,不放过在这个历程中在脑海内里一闪而过的任何疑问。

这一小节分享的是Dubbo负载平衡计谋之一最小活跃数(LeastActiveLoadBalance)。以是我先搭建一个 Dubbo 的项目,并启动三个 provider 供 consumer 挪用。

三个 provider 的 loadbalance 均设置的是 leastactive。权重划分是默认权重、200、300。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第27张**默认权重是若干?**后面看源码的时刻,源码会告诉你。

三个差异的服务提供者会给挪用方返回自己是什么权重的服务。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第28张

启动三个实例。(注:上面的 provider.xml 和 DemoServiceImpl 实在只有一个,每次启动的时刻动修改端口、权重即可。)

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第29张

到 zookeeper 上检查一下,服务提供者是否正常:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第30张可以看到三个服务提供者划分在 20880、20881、20882 端口。(每个红框的最后5个数字就是端口号)。

最后,我们再看服务消费者。消费者很简朴,设置consumer.xml

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第31张

直接挪用接口并打印返回值即可。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第32张

断点打在哪?

信赖许多同伙也很想看源码,然则不知道从那边下手。处于一种在源码内里"乱逛"的状态,一圈逛下来,收获并不大。

这一部门我想分享一下我是怎么去看源码。首先我会带着问题去源码内里寻找谜底,即有针对性的看源码。

若是是这种框架类的,正如上面写的,我会先翻一翻官网(Dubbo 的官方文档实在写的挺好了),然后搭建一个简朴的 Demo 项目,然后 Debug 跟进去看。Debug 的时刻固然需要是设置断点的,那么这个断点若何设置呢?

第一个断点,固然毋庸置疑,是打在挪用方式的地方,好比本文中,第一个断点是在这个地方:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第33张

接下里怎么办?

你固然可以从第一个断点处,一步一步的跟进去。然则在这个历程中,你发现了吗?大多数情形你都是被源码牵着鼻子走的。原本你就只带着一个问题去看源码的,有可能你Debug了十分钟,还没找到要害的代码。也有可能你Debug了十分钟,问题从一个酿成了无数个。

以是不要慌,我们点支烟,逐步剖析。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第34张

首先怎么制止被源码牵着四处乱逛呢?

我们得找到一个突破口,还记得我在《很开心,在使用mybatis的历程中我踩到一个坑》这篇文章中提到的逆向排查的方式吗?这次的文章,我再次展示一下该方式。

看源码之前,我们的目的要十分明确,就是想要找到 Dubbo 最小活跃数算法的详细实现类以及实现类的详细逻辑是什么。

凭据我们的 provider.xml 内里的:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第35张

很明显,我们知道 loadbalance 是要害字。以是我们拿着 loadbalance 全局搜索,可以看到 Dubbo 包下面的 LoadBalance。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第36张

这是一个 SPI 接口 com.alibaba.dubbo.rpc.cluster.LoadBalance:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第37张

实在现类为:

com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance

AbstractLoadBalance 是一个抽象类,该类内里有一个抽象方式doSelect。这个抽象方式其中的一个实现类就是我们要剖析的最少活跃次数负载平衡的源码。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第38张

同时,到这里我们知道了 LoadBalance 是一个 SPI 接口,说明我们可以扩展自己的负载平衡计谋。抽象方式 doSelect 有四个实现类。这个四个实现类,就是 Dubbo 官方提供的负载平衡计谋(停止 2.7.7 版本之前),他们划分是:

  1. ConsistentHashLoadBalance 一致性哈希算法
  2. LeastActiveLoadBalance 最小活跃数算法
  3. RandomLoadBalance 加权随机算法
  4. RoundRobinLoadBalance 加权轮询算法

我们已经找到了 LeastActiveLoadBalance 这个类了,那么我们的第二个断点打在那里已经很明确了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第39张

现在看来,两个断点就可以支持我们的剖析了。

有的同伙可能想问,那我想知道 Dubbo 是怎么识别出我们想要的是最少活跃次数算法,而不是其他的算法呢?其他的算法是怎么实现的呢?从第一个断点到第二个断点直接有着怎样的挪用链呢?

在没有彻底搞清晰最少活跃数算法之前,这些一切先纪录在案但不予理睬。一定要明确目的,带着一个问题进来,就先把带来的问题解决了。之后再去解决在这个历程中碰着的其他问题。在这样环环相扣解决问题的历程中,你就逐步的掌握了源码的精髓。这是我小我私家的一点看源码的心得。供诸君参考。

模拟环境

既然叫做最小活跃数计谋。那我们得让现有的三个消费者都有一些挪用次数。以是我们得革新一下服务提供者和消费者。

服务提供者端的革新如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第40张!

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第41张

PS:这里以权重为 300 的服务端为例。另外的两个服务端革新点相同。

客户端的革新点如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第42张一共发送 21 个请求:其中前 20 个先发到服务端让其 hold 住(由于服务端有 sleep),最后一个请求就是我们需要 Debug 跟踪的请求。

运行一下,让程序停在断点的地方,然后看看控制台的输出:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第43张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第44张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第45张

权重为300的服务端共计收到9个请求

权重为200的服务端共计收到6个请求

默认权重的服务端共计收到5个请求

我们另有一个请求在 Debug。直接进入到我们的第二个断点的位置,并 Debug 到下图所示的一行代码(可以点看查看大图):

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第46张

正如上面这图所说的:weight=100 回覆了一个问题,active=0 提出的一个问题。

weight=100 回覆了什么问题呢?

默认权重是若干?是 100。

我们服务端的活跃数划分应该是下面这样的

  • 权重为300的服务端,active=9
  • 权重为200的服务端,active=6
  • 默认权重(100)的服务端,active=5

然则这里为什么截图中的active会即是 0 呢?这是一个问题。

继续往下 Debug 你会发现,每一个服务端的 active 都是 0。以是相比之下没有一个 invoker 有最小 active 。于是程序走到了凭据权重选择 invoker 的逻辑中。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第47张

active为什么是0?

active 为 0 说明在 Dubbo 挪用的历程中 active 并没有发生转变。那 active 为什么是 0,实在就是在问&NBsp;active 什么时刻发生转变

要回覆这个问题我们得知道 active 是在那里界说的,由于在其界说的地方,必有其修改的方式。

下面这图说明晰active是界说在RpcStatus类内里的一个类型为AtomicInteger 的成员变量。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第48张

在 RpcStatus 类中,有三处()挪用 active 值的方式,一个增添、一个削减、一个获取:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第49张

很明显,我们需要看的是第一个,在那里增添。

以是我们找到了 beginCount(URL,String) 方式,该方式只有两个 Filter 挪用。ActiveLimitFilter,见名知意,这就是我们要找的器械。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第50张

com.alibaba.dubbo.rpc.filter.ActiveLimitFilter详细如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第51张

看到这里,我们就知道怎么去回覆这个问题了:为什么active是0呢?由于在客户端没有设置ActiveLimitFilter。以是,ActiveLimitFilter没有生效,导致active没有发生转变。

怎么让其生效呢?已经呼之欲出了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第52张

好了,再来试验一次:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第53张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第54张

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第55张加上Filter之后,我们通过Debug可以看到,对应权重的活跃数就和我们预期的是一致的了。

1.权重为300的活跃数为6

2.权重为200的活跃数为11

3.默认权重(100)的活跃数为3

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第56张

凭据活跃数我们可以剖析出来,最后我们Debug住的这个请求,一定会选择默认权重的invoker去执行,由于他是当前活跃数最小的invoker。如下所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第57张

虽然到这里我们还没最先举行源码的剖析,只是把流程梳理清晰了。然则把Demo完整的搭建了起来,而且知道了最少活跃数负载平衡算法必须配合ActiveLimitFilter使用,位于RpcStatus类的active字段才会起作用,否则,它就是一个基于权重的算法。

比起其他地方直接告诉你,要设置ActiveLimitFilter才行哦,我们自己实验得出的结论,能让我们的印象加倍深刻。

我们再仔细看一下加上ActiveLimitFilter之后的各个服务的活跃数情形:

  • 权重为300的活跃数为6
  • 权重为200的活跃数为11
  • 默认权重(100)的活跃数为3

你不以为新鲜吗,为什么权重为200的活跃数是最高的

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第58张

其在营业上的寄义是:我们有三台性能各异的服务器,A服务器性能最好,以是权重为300,B服务器性能中等,以是权重为200,C服务器性能最差,以是权重为100。

当我们选择最小活跃次数的负载平衡算法时,我们期望的是性能最好的A服务器负担更多的请求,而真实的情形是性能中等的B服务器负担的请求更多。这与我们的设定相悖。

若是你说20个请求数据量太少,可能是巧合,不足以说明问题。说明你还没被我带偏,我们不能基于巧合编程。

以是为了验证这个地方确实有问题,我把请求扩大到一万个。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第59张

同时,记得扩大 provider 端的 Dubbo 线程池:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第60张由于每个服务端运行的代码都是一样的,以是我们期望的效果应该是权重最高的负担更多的请求。然则最终的效果如图所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第61张

各个服务器均摊了请求。这就是我文章最最先的时刻说的Dubbo 2.6.0 版本中最小活跃数负载平衡算法的Bug之一。

接下来,我们带着这个问题,去剖析源码。

剖析源码

com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance的源码如下,我逐行举行领会读。可以点开查看大图,细细品读,异常爽:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第62张

下图中红框框起来的部门就是一个基于权重选择invoker的逻辑:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第63张我给人人绘图剖析一下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第64张

请仔细剖析图中给出的举例说明。同时,上面这图也是根据比例画的,可以直观的看到,对于某一个请求,区间(权重)越大的服务器,就越可能会负担这个请求。以是,当请求足够多的时刻,各个服务器负担的请求数,应该就是区间,即权重的比值。

其中第 81 行有挪用 getWeight 方式,位于抽象类 AbstractLoadBalance 中,也需要举行重点解读的代码。

com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance 的源码如下,我也举行了大量的备注:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第65张

在 AbstractLoadBalance 类中提到了一个预热的观点。官网中是这样的先容该功效的:

权重的盘算历程主要用于保证当服务运行时长小于服务预热时间时,对服务举行降权,制止让服务在启动之初就处于高负载状态。服务预热是一个优化手段,与此类似的另有 JVM 预热。主要目的是让服务启动后“低功率”运行一段时间,使其效率逐步提升至最佳状态。

从上图代码内里的公式(演变后):*盘算后的权重=(uptime/warmup)weight 可以看出:随着服务启动时间的增添(uptime),盘算后的权重会越来越靠近weight。从现实场景的角度来看,随着服务启动时间的增添,服务负担的流量会逐步上升,没有一个陡升的历程。以是这是一个优化手段。同时 Dubbo 接口还支持延迟露出。

在仔细的看完上面的源码剖析图后,配合官网的总结加上我的灵魂画作,信赖你可以对最小活跃数负载平衡算法有一个对照深入的明了:

  1. 遍历 invokers 列表,寻找活跃数最小的 Invoker
  2. 若是有多个 Invoker 具有相同的最小活跃数,此时纪录下这些 Invoker 在 invokers 聚集中的下标,并累加它们的权重,对照它们的权重值是否相等
  3. 若是只有一个 Invoker 具有最小的活跃数,此时直接返回该 Invoker 即可
  4. 若是有多个 Invoker 具有最小活跃数,且它们的权重不相等,此时处置方式和 RandomLoadBalance 一致
  5. 若是有多个 Invoker 具有最小活跃数,但它们的权重相等,此时随机返回一个即可

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第66张

以是我以为最小活跃数负载平衡的全称应该叫做:有最小活跃数用最小活跃数,没有最小活跃数凭据权重选择,权重一样则随机返回的负载平衡算法。

Bug在那里?

Dubbo2.6.0最小活跃数算法Bug一

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第67张

问题出在标号为 ① 和 ② 这两行代码中:

标号为 ① 的代码在url中取出的是没有经由 getWeight 方式降权处置的权重值,这个值会被累加到权重总和(totalWeight)中。

标号为 ② 的代码取的是经由 getWeight 方式处置后的权重值。

取值的差异会导致一个问题,标号为 ② 的代码的左边,offsetWeight 是一个在 [0,totalWeight) 局限内的随机数,右边是经由 getWeight 方式降权后的权重。以是在经由 leastCount 次的循环减法后,offsetWeight 在服务启动时间还没到热启动设置(默认10分钟)的这段时间内,极大可能仍然大于 0。导致不会进入到标号为 ③ 的代码中。直接到标号为 ④ 的代码处,酿成了随机挪用计谋。这与设计不符,以是是个 bug。

前面章节说的情形就是这个Bug导致的。

这个Bug对应的issues地址和pull request分为:

https://github.com/apache/dubbo/issues/904

https://github.com/apache/dubbo/pull/2172

那怎么修复的呢?我们直接对比 Dubbo 2.7.4.1 的代码:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第68张

可以看到获取weight的方式变了:从url中直接获取酿成了通过getWeight方式获取。获取到的变量名称也变了:从weight酿成了afterWarmup,加倍的见名知意。

另有一处转变是获取随机值的方式的转变,从Randmo酿成了ThreadLoaclRandom,性能获得了提升。这处转变就不睁开讲了,有兴趣的同伙可以去领会一下。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第69张

Dubbo2.6.0最小活跃数算法Bug二

这个Bug我没有遇到,然则我在官方文档上看了其形貌(官方文档中的版本是2.6.4),引用如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第70张

官网上说这个问题在2.6.5版本举行修复。我对比了2.6.0/2.6.5/2.7.4.1三个版本,发现每个版本都略有差异。如下所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第71张

图中标记为①的三处代码:

2.6.0版本的是有Bug的代码,缘故原由在上面说过了。

2.6.5版本的修复方式是获取随机数的时刻加一,以是取值局限就从**[0,totalWeight)酿成了[0,totalWeight]**,这样就可以制止这个问题。

2.7.4.1版本的取值局限照样[0,totalWeight),然则它的修复方式体现在了标记为②的代码处。2.6.0/2.6.5版本标记为②的地方都是if(offsetWeight<=0),而2.7.4.1版本酿成了if(offsetWeight<0)

你品一品,是不是效果是一样的,然则加倍优雅了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第72张同伙们,妖怪,都在细节里啊!

好了,进入下一议题。

一致性哈希负载平衡

这一部门是对于Dubbo负载平衡计谋之一的一致性哈希负载平衡的详细剖析。对源码逐行解读、凭据现实运行效果,配以厚实的图片,可能是东半球讲一致性哈希算法在Dubbo中的实现最详细的文章了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第73张本小节所示源码,没有稀奇标注的地方,均为2.7.4.1版本。

在撰写本文的历程中,发现了Dubbo2.7.0版本之后的一个bug。会导致性能问题,若是你们的负载平衡设置的是一致性哈希或者思量使用一致性哈希的话,可以领会一下。

哈希算法

在先容一致性哈希算法之前,我们看看哈希算法,以及它解决了什么问题,带来了什么问题。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第74张如上图所示,假设0,1,2号服务器都存储的有用户信息,那么当我们需要获取某用户信息时,由于我们不知道该用户信息存放在哪一台服务器中,以是需要划分查询0,1,2号服务器。这样获取数据的效率是极低的。

对于这样的场景,我们可以引入哈希算法。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第75张照样上面的场景,但条件是每一台服务器存放用户信息时是凭据某一种哈希算法存放的。以是取用户信息的时刻,也根据同样的哈希算法取即可。

假设我们要查询用户号为100的用户信息,经由某个哈希算法,好比这里的userId mod n,即100 mod 3效果为1。以是用户号100的这个请求最终会被1号服务器吸收并处置。

这样就解决了无效查询的问题。

然则这样的方案会带来什么问题呢?

扩容或者缩容时,会导致大量的数据迁徙。最少也会影响百分之50的数据。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第76张为了说明问题,我们加入一台服务器3。服务器的数目n就从3酿成了4。照样查询用户号为100的用户信息时,100 mod 4效果为0。这时,请求就被0号服务器吸收了。

当服务器数目为3时,用户号为100的请求会被1号服务器处置。

当服务器数目为4时,用户号为100的请求会被0号服务器处置。

以是,当服务器数目增添或者削减时,一定会涉及到大量数据迁徙的问题。可谓是牵一发而动全身。

对于上诉哈希算法其优点是简朴易用,大多数分库分表规则就接纳的这种方式。一样平常是提前凭据数据量,预先估算好分区数。

瑕玷是由于扩容或缩短节点导致节点数目转变时,节点的映射关系需要重新盘算,会导致数据举行迁徙。以是扩容时通常接纳翻倍扩容,制止数据映射所有被打乱,导致全量迁徙的情形,这样只会发生50%的数据迁徙。

假设这是一个缓存服务,数据的迁徙会导致在迁徙的时间段内,有缓存是失效的。

缓存失效,恐怖啊。还记得我之前的文章吗,《当周杰伦把QQ音乐干翻的时刻,作为程序猿我看到了什么?》就是讲缓存击穿、缓存穿透、缓存雪崩的场景和对应的解决方案。

一致性哈希算法

为领会决哈希算法带来的数据迁徙问题,一致性哈希算法应运而生。

对于一致性哈希算法,官方说法如下:

一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处置请求服务器之间的映射关系。一致性哈希解决了简朴哈希算法在漫衍式哈希表( Distributed Hash TABLe,DHT) 中存在的动态伸缩等问题。

什么意思呢?我用大白话加绘图的方式给你简朴的先容一下。

一致性哈希,你可以想象成一个哈希环,它由0到2^32-1个点组成。A,B,C划分是三台服务器,每一台的IP加端口经由哈希盘算后的值,在哈希环上对应如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第77张

当请求到来时,对请求中的某些参数举行哈希盘算后,也会得出一个哈希值,此值在哈希环上也会有对应的位置,这个请求会沿着顺时针的偏向,寻找最近的服务器来处置它,如下图所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第78张

一致性哈希就是这么个器械。那它是怎么解决服务器的扩容或缩短导致大量的数据迁徙的呢?

看一下当我们使用一致性哈希算法时,加入服务器会发什么事情。

当我们加入一个D服务器后,假设其IP加端口,经由哈希盘算后落在了哈希环上图中所示的位置。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第79张这时影响的局限只有图中标注了五角星的区间。这个区间的请求从原来的由C服务器处置酿成了由D服务器请求。而D到C,C到A,A到B这个区间的请求没有影响,加入D节点后,A、B服务器是无感知的。

以是,在一致性哈希算法中,若是增添一台服务器,则受影响的区间仅仅是新服务器(D)在哈希环空间中,逆时针偏向遇到的第一台服务器(B)之间的区间,其它区间(D到C,C到A,A到B)不会受到影响。

在加入了D服务器的情形下,我们再假设一段时间后,C服务器宕机了:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第80张当C服务器宕机后,影响的局限也是图中标注了五角星的区间。C节点宕机后,B、D服务器是无感知的。

以是,在一致性哈希算法中,若是宕机一台服务器,则受影响的区间仅仅是宕机服务器(C)在哈希环空间中,逆时针偏向遇到的第一台服务器(D)之间的区间,其它区间(C到A,A到B,B到D)不会受到影响。

综上所述,在一致性哈希算法中,不管是增添节点,照样宕机节点,受影响的区间仅仅是增添或者宕机服务器在哈希环空间中,逆时针偏向遇到的第一台服务器之间的区间,其它区间不会受到影响。

是不是很完善?

不是的,理想和现实的差距是伟大的。

一致性哈希算法带来了什么问题?

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第81张当节点很少的时刻可能会泛起这样的漫衍情形,A服务会负担大部门请求。这种情形就叫做数据倾斜。

怎么解决数据倾斜呢?加入虚拟节点。

怎么去明了这个虚拟节点呢?

首先一个服务器凭据需要可以有多个虚拟节点。假设一台服务器有n个虚拟节点。那么哈希盘算时,可以使用IP+端口+编号的形式举行哈希值盘算。其中的编号就是0到n的数字。由于IP+端口是一样的,以是这n个节点都是指向的统一台机械。

如下图所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第82张在没有加入虚拟节点之前,A服务器负担了绝大多数的请求。然则假设每个服务器有一个虚拟节点(A-1,B-1,C-1),经由哈希盘算后落在了如上图所示的位置。那么A服务器的负担的请求就在一定程度上(图中标注了五角星的部门)分摊给了B-1、C-1虚拟节点,现实上就是分摊给了B、C服务器。

一致性哈希算法中,加入虚拟节点,可以解决数据倾斜问题。

当你在面试的历程中,若是听到了类似于数据倾斜的字眼。那也许率是在问你一致性哈希算法和虚拟节点。

在先容了相关靠山后,我们可以去看看一致性哈希算法在Dubbo中的应用了。

一致性哈希算法在Dubbo中的应用

前面我们说了Dubbo中负载平衡的实现是通过org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance中的 doSelect 抽象方式实现的,一致性哈希负载平衡的实现类如下所示:

org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第83张

由于一致性哈希实现类看起来稍微有点抽象,不太好演示,以是我想到了一个"骚"操作。前面的文章说过 LoadBalance 是一个 SPI 接口:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第84张

既然是一个 SPI 接口,那我们可以自己扩展一个一模一样的算法,只是在算法内里加入一点输出语句利便我们考察情形。怎么扩展 SPI 接口就不形貌了,只要记着代码内里的输出语句都是额外加的,此外没有任何改动即可,如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第85张

整个类如下图片所示,请先看完整个类,有一个整体的观点后,我会举行方式级别的剖析。

图片很长,其中我加了许多注释和输出语句,可以点开大图查看,一定会帮你加倍好的明了一致性哈希在Dubbo中的应用:

革新之后,我们先把程序跑起来,有了输出就好剖析了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第86张服务端代码如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第87张其中的端口是需要手动修改的,我划分启动服务在20881和20882端口。

项目中provider.xml设置如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第88张consumer.xml设置如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第89张然后,启动在20881和20882端口划分启动两个服务端。客户端消费如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第90张

运行效果输出如下,可以先看个也许的输出,下面会对每一部门输出举行逐一的解读

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第91张

好了,用例也跑起来了,日志也有了。接下来最先连系代码和日志举行方式级别的剖析。

首先是doSelect方式的入口:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第92张从上图我们知道了,第一次挪用需要对selectors举行put操作,selectors的 key 是接口中界说的方式,value 是 ConsistentHashSelector 内部类

ConsistentHashSelector通过挪用其组织函数举行初始化的。invokers(服务端)作为参数通报到了组织函数中,组织函数内里的逻辑,就是把服务端映射到哈希环上的历程,请看下图,连系代码,仔细剖析输出数据:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第93张从上图可以看出,当 ConsistentHashSelector 的组织方式挪用完成后,8个虚拟节点在哈希环上已经映射完成。两台服务器,每一台4个虚拟节点组成了这8个虚拟节点。

doSelect方式继续执行,并打印出每个虚拟节点的哈希值和对应的服务端,请仔细品读下图:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第94张

说明一下:上面图中的哈希环是没有思量比例的,仅仅是展现了两个服务器在哈希环上的相对位置。而且为了演示说明利便,仅仅只有8个节点。假设我们有4台服务器,每台服务器的虚拟节点是默认值(160),这个情形下哈希环上一共有160*4=640个节点。

哈希环映射完成后,接下来的逻辑是把这次请求经由哈希盘算后,映射到哈希环上,并顺时针偏向寻找遇到的第一个节点,让该节点处置该请求:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第95张

还记得地址为 468e8565 的 A 服务器是什么端口吗?前面的图片中有哦,该服务对应的端口是 20882 。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第96张

最后我们看看输出效果:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第97张

和我们预期的一致。整个挪用就算是完成了。

再对两个方式举行一个弥补说明。

第一个方式是 selectForKey,这个方式内里逻辑如下图所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第98张

虚拟节点都存储在 TreeMap 中。顺时针查询的逻辑由 TreeMap 保证。看一下下面的 Demo 你就明了了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第99张

第二个方式是 hash 方式,其中的 & 0xFFFFFFFFL 的目的如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第100张

&是位运算符,而 0xFFFFFFFFL 转换为四字节显示后,其低32位全是1,以是保证了哈希环的局限是 [0,Integer.MAX_VALUE]:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第101张

以是这里我们可以革新这个哈希环的局限,假设我们改为 100000。十进制的 100000 对于的 16 进制为 186A0 。以是我们革新后的哈希算法为:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第102张

再次挪用后可以看到,盘算后的哈希值都在10万以内。然则漫衍极不平均,说明修改数据后这个哈希算法不是一个优异的哈希算法:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第103张以上,就是对一致性哈希算法在Dubbo中的实现的解读。需要特殊说明一下的是,一致性哈希负载平衡计谋和权重没有任何关系

我又发现了一个BUG

前面我先容了Dubbo 2.6.5版本之前,最小活跃数算法的两个 bug。

很不幸,这次我又发现了Dubbo 2.7.4.1版本,一致性哈希负载平衡计谋的一个bug,我提交了issue 地址如下:

https://github.com/apache/dubbo/issues/5429

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第104张

我在这里详细说一下这个Bug征象、缘故原由和我的解决方案。

征象如下,我们挪用三次服务端:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第105张

输出日志如下(有部门删减):

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第106张

可以看到,在三次挪用的历程中并没有发生服务的上下线操作,然则每一次挪用都重新举行了哈希环的映射。而我们预期的效果是应该只有在第一次挪用的时刻举行哈希环的映射,若是没有服务上下线的操作,后续请求凭据已经映射好的哈希环举行处置。

上面输出的缘故原由是由于每次挪用的invokers的identityHashCode发生了转变:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第107张

我们看一下三次挪用invokers的情形:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第108张

经由debug我们可以看出由于每次挪用的invokers地址值不是统一个,以是System.identityHashCode(invokers)方式返回的值都不一样。

接下来的问题就是为什么每次挪用的invokers地址值都不一样呢?

经由Debug之后,可以找到这个地方:

org.apache.dubbo.rpc.cluster.RouterChAIn#route

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第109张

问题就出在这个TagRouter中:

org.apache.dubbo.rpc.cluster.router.tag.TagRouter#filterInvoker

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第110张

以是,在TagRouter中的stream操作,改变了invokers,导致每次挪用时其

System.identityHashCode(invokers)返回的值不一样。以是每次挪用都市举行哈希环的映射操作,在服务节点多,虚拟节点多的情形下会有一定的性能问题。

到这一步,问题又发生了转变。这个TagRouter怎么来的呢

若是领会Dubbo 2.7.x版本新特征的同伙可能知道,标签路由是Dubbo2.7引入的新功效。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第111张

通过加载下面的设置加载了RouterFactrory:

META-INF\dubbo\internal\org.apache.dubbo.rpc.cluster.RouterFactory(Dubbo 2.7.0版本之前)

META-INF\dubbo\internal\com.alibaba.dubbo.rpc.cluster.RouterFactory(Dubbo 2.7.0之前)

下面是Dubbo 2.6.7(2.6.x的最后一个版本)和Dubbo 2.7.0版本该文件的对比:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第112张可以看到确实是在 Dubbo 2.7.0 之后引入了 TagRouter。

至此,Dubbo 2.7.0 版本之后,一致性哈希负载平衡算法的 Bug 的前因后果也先容清晰了。

解决方案是什么呢?稀奇简朴,把获取 identityHashCode 的方式从 System.identityHashCode(invokers) 修改为 invokers.hashCode() 即可。

此方案是我提的 issue 内里的谈论,这里 System.identityHashCode 和 hashCode 之间的联系和区别就不举行睁开讲述了,不清晰的人人可以自行领会一下。

(我的另外一篇文章:够强!一行代码就修复了我提的Dubbo的Bug。)

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第113张

改完之后,我们再看看运行效果:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第114张

可以看到第二次挪用的时刻并没有举行哈希环的映射操作,而是直接取到了值,举行挪用。

加入节点,绘图剖析

最后,我再剖析一种情形。在A、B、C三个服务器(20881、20882、20883端口)都在正常运行,哈希映射已经完成的情形下,我们再启动一个D节点(20884端口),这时的日志输出和对应的哈希环转变情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第115张

凭据日志作图如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第116张

凭据输出日志和上图再加上源码,你再细细回味一下。我小我私家以为照样讲的异常详细了。

一致性哈希的应用场景

当人人谈到一致性哈希算法的时刻,首先的第一印象应该是在缓存场景下的使用,由于在一个优异的哈希算法加持下,其上下线节点对整体数据的影响(迁徙)都是对照友好的。

然则想一下为什么 Dubbo 在负载平衡计谋内里提供了基于一致性哈希的负载平衡计谋?它的现实使用场景是什么?

我最最先也想不明了。我想的是在 Dubbo 的场景下,假设需求是想要一个用户的请求一直让一台服务器处置,那我们可以接纳一致性哈希负载平衡计谋,把用户号举行哈希盘算,可以实现这样的需求。然则这样的需求未免有点太牵强了,适用场景略小。

直到有天晚上,我睡觉之前,电光火石之间突然想到了一个稍微适用的场景了。

若是需求是需要保证某一类请求必须顺序处置呢?

若是你用其他负载平衡计谋,请求分发到了差异的机械上去,就很难保证请求的顺序处置了。好比A,B请求要求顺序处置,现在A请求先发送,被负载到了A服务器上,B请求后发送,被负载到了B服务器上。而B服务器由于性能好或者当前没有其他请求或者其他缘故原由极有可能在A服务器还在处置A请求之前就把B请求处置完成了。这样不符合我们的要求。

这时,一致性哈希负载平衡计谋就上场了,它帮我们保证了某一类请求都发送到牢固的机械上去执行。好比把统一个用户的请求发送到统一台机械上去执行,就意味着把某一类请求发送到统一台机械上去执行。以是我们只需要在该机械上运行的程序中保证顺序执行就行了,好比你加一个行列。

一致性哈希算法+行列,可以实现顺序处置的需求。

好了,一致性哈希负载平衡算法就写到这里。

继续进入下一个议题。

加权轮询负载平衡

这一小节是对于Dubbo负载平衡计谋之一的加权随机算法的详细剖析。

从 2.6.4 版本聊起,该版本在某些情形下存在着对照严重的性能问题。由问题入手,层层深入,领会该算法在 Dubbo 中的演变历程,读懂它的宿世今生。

什么是轮询?

在形貌加权轮询之前,先注释一下什么是轮询算法,如下图所示:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第117张假设我们有A、B、C三台服务器,共计处置6个请求,服务处置请求的情形如下:

  1. 第一个请求发送给了A服务器
  2. 第二个请求发送给了B服务器
  3. 第三个请求发送给了C服务器
  4. 第四个请求发送给了A服务器
  5. 第五个请求发送给了B服务器
  6. 第六个请求发送给了C服务器
  7. ......

上面这个例子演示的历程就叫做轮询。可以看出,所谓轮询就是将请求轮流分配给每台服务器

轮询的优点是无需纪录当前所有服务器的链接状态,以是它一种无状态负载平衡算法,实现简朴,适用于每台服务器性能相近的场景下。

轮询的瑕玷也是显而易见的,它的应用场景要求所有服务器的性能都相同,异常的局限。

大多数现实情形下,服务器性能是各有差异,针对性能好的服务器,我们需要让它负担更多的请求,即需要给它配上更高的权重。

以是加权轮询,应运而生。

什么是加权轮询?

为领会决轮询算法应用场景的局限性。当遇到每台服务器的性能不一致的情形,我们需要对轮询历程举行加权,以调控每台服务器的负载。

经由加权后,每台服务器能够获得的请求数比例,靠近或即是他们的权重比。好比服务器 A、B、C 权重比为 5:3:2。那么在10次请求中,服务器 A 将收到其中的5次请求,服务器 B 会收到其中的3次请求,服务器 C 则收到其中的2次请求。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第118张

这里要和加权随机算法做区分哦。直接把前面先容的加权随机算法画的图拿过来:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第119张上面这图是根据比例画的,可以直观的看到,对于某一个请求,区间(权重)越大的服务器,就越可能会负担这个请求。以是,当请求足够多的时刻,各个服务器负担的请求数,应该就是区间,即权重的比值。

假设有A、B、C三台服务器,权重之比为5:3:2,一共处置10个请求。

那么负载平衡接纳加权随机算法时,很有可能A、B服务就处置完了这10个请求,由于它是随机挪用。

接纳负载平衡接纳轮询加权算法时,A、B、C服务一定是划分负担5、3、2个请求。

Dubbo2.6.4版本的实现

对于Dubbo2.6.4版本的实现剖析,可以看下图,我加了许多注释,其中的输出语句都是我加的:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第120张

示例代码照样沿用之前文章中的Demo,这里划分在 20881、20882、20883 端口启动三个服务,各自的权重划分为 1,2,3。

客户端挪用 8 次:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第121张输出效果如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第122张可以看到第七次挪用后mod=0,回到了第一次挪用的状态。形成了一个闭环。

再看看判断的条件是什么:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第123张其中mod在代码中扮演了极其主要的角色,mod凭据一个方式的挪用次数差异而差异,取值局限是[0,weightSum)。

由于weightSum=6,以是枚举mod差异值时,最终的选择效果和权重转变:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第124张

可以看到20881,20882,20883负担的请求数目比值为1:2:3。同时我们可以看出,当 mod >= 1 后,20881端口的服务就不会被选中了,由于它的权重被减为0了。当 mod >= 4 后,20882端口的服务就不会被选中了,由于它的权重被减为0了。

连系判断条件和输出效果,我们详细剖析一下(下面内容稍微有点绕,若是看不懂,多连系上面的图片看几回):

第一次挪用

mod=0,第一次循环就知足代码块①的条件,直接返回当前循环的invoker,即20881端口的服务。此时各端口的权重情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第125张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第126张

第二次挪用

mod=1,需要进入代码块②,对mod举行一次递减。

第一次循环对20881端口的服务权重减一,mod-1=0。

第二次循环,mod=0,循环对象是20882端口的服务,权重为2,知足代码块①,返回当前循环的20882端口的服务。

此时各端口的权重情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第127张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第128张

第三次挪用

mod=2,需要进入代码块②,对mod举行两次递减。

第一次循环对20881端口的服务权重减一,mod-1=1;

第二次循环对20882端口的服务权重减一,mod-1=0;

第三次循环时,mod已经为0,当前循环的是20883端口的服务,权重为3,知足代码块①,返回当前循环的20883端口的服务。

此时各端口的权重情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第129张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第130张

第四次挪用

mod=3,需要进入代码块②,对mod举行三次递减。

第一次循环对20881端口的服务权重减一,从1变为0,mod-1=2;

第二次循环对20882端口的服务权重减一,从2变为1,mod-1=1;

第三次循环对20883端口的服务权重减一,从3变为2,mod-1=0;

第四次循环的是20881端口的服务,此时mod已经为0,然则20881端口的服务的权重已经变为0了,不知足代码块①和代码块②,进入第五次循环。

第五次循环的是20882端口的服务,当前权重为1,mod=0,知足代码块①,返回20882端口的服务。

此时各端口的权重情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第131张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第132张

第五次挪用

mod=4,需要进入代码块②,对mod举行四次递减。

第一次循环对20881端口的服务权重减一,从1变为0,mod-1=3;

第二次循环对20882端口的服务权重减一,从2变为1,mod-1=2;

第三次循环对20883端口的服务权重减一,从3变为2,mod-1=1;

第四次循环的是20881端口的服务,此时mod为1,然则20881端口的服务的权重已经变为0了,不知足代码块②,mod稳定,进入第五次循环。

第五次循环时,mod为1,循环对象是20882端口的服务,权重为1,知足代码块②,权重从1变为0,mod从1变为0,进入第六次循环。

第六次循环时,mod为0,循环对象是20883端口的服务,权重为2,知足条件①,返回当前20883端口的服务。

此时各端口的权重情形如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第133张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第134张

第六次挪用

第六次挪用,mod=5,会循环九次,最终选择20883端口的服务,读者可以自行剖析一波,剖析出来了,就领会的透透的了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第135张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第136张

第七次挪用

第七次挪用,又回到mod=0的状态:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第137张必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第138张

2.6.4版本的加权轮询就剖析完了,然则事情并没有这么简朴。这个版本的加权轮询是有性能问题的。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第139张

该问题对应的issue地址如下:

https://github.com/apache/dubbo/issues/2578

问题泛起在invoker返回的时机上:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第140张

截取issue内里的一个回覆:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第141张

10分钟才选出一个invoker,还怎么玩?

有时间可以读一读这个issue,内里各路大神针对该问题举行了猛烈的讨论,第一种革新方案被接受后,很快就被推翻,被第二种方案取代,可以说优化思绪十分值得学习,很精彩,接下来的行文门路就是根据该issue睁开的。

推翻,重修。

上面的代码时间庞大度是O(mod),而第一次修复之后时间庞大度降低到了常量级别。可以说是一次异常优异的优化,值得我们学习,看一下优化之后的代码:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第142张

其要害优化的点是这段代码,我加入输出语句,便于剖析。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第143张

输出日志如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第144张

把上面的输出转化到表格中去,7次请求的选择历程如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第145张

该算法的原理是:

把服务端都放到聚集中(invokerToWeightList),然后获取服务端个数(length),并盘算出服务端权重最大的值(maxWeight)。

index示意本次请求到来时,处置该请求的服务端下标,初始值为0,取值局限是[0,length)。

currentWeight示意当前调剂的权重,初始值为0,取值局限是[0,maxWeight)。

当请求到来时,从index(就是0)最先轮询服务端聚集(invokerToWeightList),若是是一轮循环的最先(index=0)时,则对currentWeight举行加一操作(不会跨越maxWeight),在循环中找出第一个权重大于currentWeight的服务并返回。

这里说的一轮循环是指index再次变为0所经历过的循环,这里可以把index=0看做是一轮循环的最先。每一轮循环的次数与Invoker的数目有关,Invoker数目通常不会太多,以是我们可以以为上面代码的时间庞大度为常数级。

从issue上看出,这个算法最终被merged了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第146张

然则很快又被推翻了:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第147张

这个算法不够平滑。什么意思呢?

翻译一下上面的内容就是:服务器[A, B, C]对应权重[5, 1, 1]。举行7次负载平衡后,选择出来的序列为[A, A, A, A, A, B, C]。前5个请求所有都落在了服务器A上,这将会使服务器A短时间内吸收大量的请求,压力陡增。而B和C此时无请求,处于空闲状态。而我们期望的效果是这样的[A, A, B, A, C, A, A],差异服务器可以穿插获取请求。

我们设置20881端口的权重为5,20882、20883端口的权重均为1。

举行实验,发现确实云云:可以看到一共举行7次请求,第1次到5次请求都分发给了权重为5的20881端口的服务,前五次请求,20881和20882都处于空闲状态:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第148张

转化为表格如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第149张

从表格的最终效果一栏也可以直观的看出,七次请求对应的服务器端口为:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第150张

漫衍确实不够平均。

再推翻,再重修,平滑加权。

从issue中可以看到,再次重构的加权算法的灵感泉源是Nginx的平滑加权轮询负载平衡

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第151张

看代码之前,先先容其盘算历程。

假设每个服务器有两个权重,一个是设置的weight,不会转变,一个是currentWeight会动态调整,初始值为0。当有新的请求进来时,遍历服务器列表,让它的currentWeight加上自身权重。遍历完成后,找到最大的currentWeight,并将其减去权重总和,然后返回响应的服务器即可。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第152张

若是你照样不知道上面的表格是若何算出来的,我再给你详细的剖析一下第1、2个请求的盘算历程:

第一个请求盘算历程如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第153张

第二个请求盘算历程如下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第154张

后面的请求你就可以自己剖析了。

从表格的最终效果一栏也可以直观的看出,七次请求对应的服务器端口为:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第155张

可以看到,权重之比同样是5:1:1,然则最终的请求分发的就对照的"平滑"。对比一下:

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第156张对于平滑加权算法,我想多说一句。我以为这个算法异常的神奇,我是彻底的明了了它每一步的盘算历程,知道它最终会形成一个闭环,然则我想了良久,我照样不知道背后的数学原理是什么,不明了为什么会形成一个闭环,异常的神奇。

很正常,我不纠结的,程序猿的事情不就是这样吗?我也不知道为什么,它能事情。别问,问就是玄学,若是一定要说出点什么的话,我想,我愿称之为:绝活吧。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第157张然则我们只要能够明了我前面所表达的平滑加权轮询算法的盘算历程,知道其最终会形成闭环,就能明了下面的代码。配合代码中的注释食用,效果更佳。

以下代码以及注释泉源官网:

http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第158张

总结

好了,到这里关于Dubbo的五种负载平衡计谋就讲完了。简朴总结一下:(加权随机算法在讲最小活跃数算法的时刻提到过,由于原理十分简朴,这里就不专门拿出章节来形貌了。)

最短响应时间负载平衡:在所有服务提供者中选出平均响应时间最短的一个,若是能选出来,则使用选出来的一个。若是不能选出来多个,再凭据权重选,若是权重也一样,则随机选择。

一致性哈希负载平衡:在一致性哈希算法中,不管是增添节点,照样宕机节点,受影响的区间仅仅是增添或者宕机服务器在哈希环空间中,逆时针偏向遇到的第一台服务器之间的区间,其它区间不会受到影响。为领会决数据倾斜的问题,引入了虚拟节点的观点。一致性哈希算法是 Dubbo 中唯逐一个与权重没有任何关系的负载平衡算法,可以保证相同参数的请求打到统一台机械上。

最小活跃数负载平衡:需要配合 activeFilter 使用,活跃数在方式挪用前后举行维护,响应越快的服务器聚积的请求越少,对应的活跃数也少。Dubbo 在选择的时刻遵照下面的规则,有最小活跃数用最小活跃数,没有最小活跃数凭据权重选择,权重一样则随机返回的负载平衡算法。

加权随机算法:随机,顾名思义,就是从多个服务提供者中随机选择一个出来。加权,就是指需要根据权重设置随机概率。常见场景就是对于性能好的机械可以把对应的权重设置的大一点,而性能相对较差的,权重设置的小一点。哎,像极了这个社会上的某些征象,对外宣传是随机摇号,背后指不定有一群权重高的人呢。

加权轮询负载平衡:轮询就是雨露均沾的意思,所有的服务提供者都需要挪用。而当轮询遇到加权则可以让请求(岂论若干)严酷根据我们的权重之比举行分配。好比有A、B、C三台服务器,权重之比为5:3:2,一共处置10个请求。那么接纳负载平衡接纳轮询加权算法时,A、B、C服务一定是划分负担5、3、2个请求。同时需要注重的是加权轮询算法的两次升级历程,以及最终的“平滑”的解决方案。

再说一件事

本文主要聊的是负载平衡嘛,让我想起了 2019 年阿里巴巴第五届中间件挑战赛的预赛赛题也是实现一个负载平衡计谋。

详细的赛题可以看这里:

https://tianchi.aliyun.com/competition/entrance/231714/information

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第159张

这种竞赛照样很有意思的,你报名之后仅仅是读懂赛题,然后自己多想想怎么实现,哪怕是不提交代码,在竞赛完成后看前几名的赛题剖析,再去把他们的代码拉下来看看,你就会发现,实在最终的思绪都大同小异,差异会体现在参数调优和代码优化程度上。

固然最大的差异照样会体现在语言的层面。若是不限制参数语言的话,JAVa 系的选手一定是被 C 系选手吊打的。

然则,被吊打不主要,主要的是真的能学到许多的器械,而这些器械,在绝大部门事情中是很难学到的。

最近,阿里巴巴第六届中间件挑战赛也最先了,可以看一下这个链接:

https://tianchi.aliyun.com/competition/entrance/231790/introduction?spm=5176.12281968.1008.3.65818188YmzFqa

这次是分为三个赛道,选择性更多了。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第160张

作为这个竞赛的历久关注者(连续关注三年了吧),这次作为一个自来水免费宣传一波。

同伙,我至心建议你去看一下,报个名,玩一玩,收获真的很大的。

固然,若是能在报名的时刻邀请人那一栏填【why手艺】,我至心谢谢你。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第161张

最后说一句(求关注)

点个“赞”吧,周更很累的,不要白嫖我,需要一点正反馈。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第162张才疏学浅,难免会有纰漏,若是你发现了错误的地方,还请你留言指出来,我对其加以修改。

谢谢您的阅读,我坚持原创,十分迎接并谢谢您的关注。

我是 why,一个被代码延迟的文学创作者,不是大佬,然则喜欢分享,是一个又暖又有料的四川好男子。

迎接关注我的微信民众号:why手艺。在这里我会分享一些java手艺相关的知识,用匠心敲代码,对每一行代码卖力。偶然也会荒腔走板的聊一聊生涯,写一写书评、影评。谢谢你的关注,愿你我共同进步。

必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。 第163张

,

欧博官网

www.cxculb.com欢迎进入欧博官网(Allbet Game),欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:必威体育betway登录:吐血输出:2万字长文带你细细清点五种负载平衡计谋。

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:657
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1016
  • 评论总数:245
  • 浏览总数:10378