2 万字长文盘点五种负载均衡策略
作者 | why技术
来源 | why技术
责编 | 王晓曼
荒腔走板
老规矩,在技术分享开始之前,先荒腔走板,聊点别的。给枯燥的技术文章注入一抹其它的色彩。
上面的图片,是我在骑车的过程中拍的。衣服随意的绑在驼包上,两侧各挂着一只鞋子,左边是一望无际的大草原,右边是笔直的泊油路。我在车尾挂了一个牌子:别急,淡定。
我记得拍这张照片的时候,我坐在路边休息的,随手拍了一张照片。现在偶然看见,觉得挺不错的,这句话我是挺想对自己说的。
2020 年很快就过去一半了,回想前半年,感觉好像自己还没有什么建树,时间就这样悄悄溜走了。
心中难免有一丝丝的慌张。就像那句歌词唱的一样:
慌慌张张匆匆忙忙,为何生活总是这样。难道说我的理想,就是这样度过一生的时光。
忙工作,忙生活,忙装修,忙文章。这些事情有的时候就像是挡在自己面前的一座座大山,当忙的不可开交的时候,偶尔也会懈怠一下,但是没有关系。
人生不就是关关难过关关过吗。
所以:别急,淡定。
Dubbo的五种负载均衡策略
2020 年 5 月 15 日,Dubbo 发布 2.7.7 release 版本。其中有这么一个 Features:
新增一个负载均衡策略。
熟悉我的老读者肯定是知道的,Dubbo 的负载均衡我都写过专门的文章,对每个负载均衡算法进行了源码的解读,还分享了自己调试过程中的一些骚操作。
新的负载均衡出来了,那必须的得解读一波。
先看一下提交记录:
https://github.com/chickenlj/incubator-dubbo/commit/6d2ba7ec7b5a1cb7971143d4262d0a1bfc826d45
负载均衡是基于 SPI 实现的,我们看到对应的文件中多了一个名为 shortestresponse 的 key。
这个,就是新增的负载均衡策略了。看名字,你也知道了这个策略的名称就叫:最短响应。
所以截止 2.7.7 版本,官方提供了五种负载均衡算法了,他们分别是:
ConsistentHashLoadBalance 一致性哈希负载均衡
LeastActiveLoadBalance 最小活跃数负载均衡
RandomLoadBalance 加权随机负载均衡
RoundRobinLoadBalance 加权轮询负载均衡
ShortestResponseLoadBalance 最短响应时间负载均衡
前面四种我已经在之前的文章中进行了详细的分析。有的读者反馈说想看合辑,所以我会在这篇文章中把之前文章也整合进来。
所以,需要特别强调一下的是,这篇文章集合了之前写的三篇负载均衡的文章。看完最短响应时间负载均衡这一部分后,如果你看过我之前的那三篇文章,你可以温故而知新,也可以直接拉到文末看看我推荐的一个活动,然后点个赞再走。如果你没有看过那三篇,这篇文章如果你细看,肯定有很多收获,以后谈起负载均衡的时候若数家珍,但是肯定需要看非常非常长的时间,做好心理准备。
我已经预感到了,这篇文章妥妥的会超过 2 万字。属于硬核劝退文章,想想就害怕。
最短响应时间负载均衡
首先,我们看一下这个类上的注解,先有个整体的认知。
org.apache.dubbo.rpc.cluster.loadbalance.ShortestResponseLoadBalance
我来翻译一下是什么意思:
从多个服务提供者中选择出调用成功的且响应时间最短的服务提供者,由于满足这样条件的服务提供者有可能有多个。所以当选择出多个服务提供者后要根据他们的权重做分析。
但是如果只选择出来了一个,直接用选出来这个。
如果真的有多个,看它们的权重是否一样,如果不一样,则走加权随机算法的逻辑。
如果它们的权重是一样的,则随机调用一个。
再配个图,就好理解了,可以先不管图片中的标号:
有了上面的整体概念的铺垫了,接下来分析源码的时候就简单了。
源码一共就 66 行,我把它分为 5 个片段去一一分析。
这里一到五的标号,对应上面流程图中的标号。我们一个个的说。
1、标号为①的部分
这一部分是定义并初始化一些参数,为接下来的代码服务的,翻译一下每个参数对应的注释:
length 参数:服务提供者的数量。
shortestResponse 参数:所有服务提供者的估计最短响应时间。(这个地方我觉得注释描述的不太准确,看后面的代码可以知道这只是一个零时变量,在循环中存储当前最短响应时间是多少。)
shortCount 参数:具有相同最短响应时间的服务提供者个数,初始化为 0。
shortestIndexes 参数:数组里面放的是具有相同最短响应时间的服务提供者的下标。
weights 参数:每一个服务提供者的权重。
totalWeight 参数:多个具有相同最短响应时间的服务提供者对应的预热(预热这个点还是挺重要的,在下面讲最小活跃数负载均衡的时候有详细说明)权重之和。
firstWeight 参数:第一个具有最短响应时间的服务提供者的权重。
sameWeight 参数:多个满足条件的提供者的权重是否一致。
2、标号为②的部分
这一部分代码的关键,就在上面框起来的部分。而框起来的部分,最关键的地方,就在于第一行。
获取调用成功的平均时间。
成功调用的平均时间怎么算的?
调用成功的请求数总数对应的总耗时 / 调用成功的请求数总数 = 成功调用的平均时间。
所以,在下面这个方法中,首先获取到了调用成功的请求数总数:
这个 succeeded 参数是怎么来的呢?
答案就是:总的请求数减去请求失败的数量,就是请求成功的总数!
那么为什么不能直接获取请求成功的总数呢?
别问,问就是没有这个选项啊。你看,在 RpcStatus 里面没有这个参数呀。
请求成功的总数我们有了,接下来成功总耗时怎么拿到的呢?
答案就是:总的请求时间减去请求失败的总时间,就是请求成功的总耗时!
那么为什么不能直接获取请求成功的总耗时呢?
别问,问就是......
我们看一下 RpcStatus 中的这几个参数是在哪里维护的:
org.apache.dubbo.rpc.RpcStatus#endCount(org.apache.dubbo.rpc.RpcStatus, long, boolean)
其中的第二个入参是本次请求调用时长,第三个入参是本次调用是否成功。
具体的方法不必细说了吧,已经显而易见了。
再回去看框起来的那三行代码:
第一行获取到了该服务提供者成功请求的平均耗时。
第二行获取的是该服务提供者的活跃数,也就是堆积的请求数。
第三行获取的就是如果当前这个请求发给这个服务提供者预计需要等待的时间。乘以 active 的原因是因为它需要排在堆积的请求的后面嘛。
这里,我们就获取到了如果选择当前循环中的服务提供者的预计等待时间是多长。
后面的代码怎么写?
当然是出来一个更短的就把这个踢出去呀,或者出来一个一样长时间的就记录一下,接着去 pk 权重了。
所以,接下来 shortestIndexes 参数和 weights 参数就排上用场了:
另外,多说一句的,它里面有这样的一行注释:
和 LeastActiveLoadBalance 负载均衡策略一致,我给你截图对比一下:
可以看到,确实是非常的相似,只是一个是判断谁的响应时间短,一个是判断谁的活跃数低。
3、标号为③的地方
标号为③的地方是这样的:
里面参数的含义我们都知道了,所以,标号为③的地方的含义就很好解释了:经过选择后只有一个服务提供者满足条件。所以,直接使用这个服务提供者。
4、标号为④的地方
这个地方我就不展开讲了(后面的加权随机负载均衡那一小节有详细说明),熟悉的朋友一眼就看出来这是加权随机负载均衡的写法了。
不信?我给你对比一下:
你看,是不是一模一样的。
5、标号为⑤的地方
一行代码,没啥说的。就是从多个满足条件的且权重一样的服务提供者中随机选择一个。
如果一定要多说一句的话,我截个图吧:
可以看到,这行代码在最短响应时间、加权随机、最小活跃数负载均衡策略中都出现了,且都在最后一行。
好了,到这里最短响应时间负载均衡策略就讲完了,你再回过头去看那张流程图,会发现其实流程非常的清晰,完全可以根据代码结构画出流程图。一个是说明这个算法是真的不复杂,另一个是说明好的代码会说话。
6、优雅
你知道 Dubbo 加入这个新的负载均衡算法提交了几个文件吗?
四个文件,其中还包含两个测试文件:
这里就是策略模式和 SPI 的好处。对原有的负载均衡策略没有任何侵略性。只需要按照规则扩展配置文件,实现对应接口即可。
这是什么?
这就是值得学习优雅!
那我们优雅的进入下一议题。
最小活跃数负载均衡
这一小节所示源码,没有特别标注的地方均为 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 不够活跃?(几年前的文章现在还有人在发。)
对吧,我们不吵架,我们摆事实,聊数据嘛。
1、Demo 准备
我看源码的习惯是先搞个 Demo 把调试环境搭起来。然后带着疑问去抽丝剥茧的 Debug,不放过在这个过程中在脑海里面一闪而过的任何疑问。
这一小节分享的是Dubbo负载均衡策略之一最小活跃数(LeastActiveLoadBalance)。所以我先搭建一个 Dubbo 的项目,并启动三个 provider 供 consumer 调用。
三个 provider 的 loadbalance 均配置的是 leastactive。权重分别是默认权重、200、300。
默认权重是多少?后面看源码的时候,源码会告诉你。
三个不同的服务提供者会给调用方返回自己是什么权重的服务。
启动三个实例。(注:上面的 provider.xml 和 DemoServiceImpl 其实只有一个,每次启动的时候手动修改端口、权重即可。)
到 zookeeper 上检查一下,服务提供者是否正常:
可以看到三个服务提供者分别在 20880、20881、20882 端口。(每个红框的最后5个数字就是端口号)。
最后,我们再看服务消费者。消费者很简单,配置consumer.xml。
直接调用接口并打印返回值即可。
2、断点打在哪?
相信很多朋友也很想看源码,但是不知道从何处下手。处于一种在源码里面"乱逛"的状态,一圈逛下来,收获并不大。
这一部分我想分享一下我是怎么去看源码。首先我会带着问题去源码里面寻找答案,即有针对性的看源码。
如果是这种框架类的,正如上面写的,我会先翻一翻官网(Dubbo 的官方文档其实写的挺好了),然后搭建一个简单的 Demo 项目,然后 Debug 跟进去看。Debug 的时候当然需要是设置断点的,那么这个断点如何设置呢?
第一个断点,当然毋庸置疑,是打在调用方法的地方,比如本文中,第一个断点是在这个地方:
接下里怎么办?
你当然可以从第一个断点处,一步一步的跟进去。但是在这个过程中,你发现了吗?大多数情况你都是被源码牵着鼻子走的。本来你就只带着一个问题去看源码的,有可能你Debug了十分钟,还没找到关键的代码。也有可能你Debug了十分钟,问题从一个变成了无数个。
所以不要慌,我们点支烟,慢慢分析。
首先怎么避免被源码牵着四处乱逛呢?
我们得找到一个突破口,还记得我在《很开心,在使用mybatis的过程中我踩到一个坑》这篇文章中提到的逆向排查的方法吗?这次的文章,我再次展示一下该方法。
看源码之前,我们的目标要十分明确,就是想要找到 Dubbo 最小活跃数算法的具体实现类以及实现类的具体逻辑是什么。
根据我们的 provider.xml 里面的:
很明显,我们知道 loadbalance 是关键字。所以我们拿着 loadbalance 全局搜索,可以看到 Dubbo 包下面的 LoadBalance。
这是一个 SPI 接口 com.alibaba.dubbo.rpc.cluster.LoadBalance:
其实现类为:
com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance
AbstractLoadBalance 是一个抽象类,该类里面有一个抽象方法doSelect。这个抽象方法其中的一个实现类就是我们要分析的最少活跃次数负载均衡的源码。
同时,到这里我们知道了 LoadBalance 是一个 SPI 接口,说明我们可以扩展自己的负载均衡策略。抽象方法 doSelect 有四个实现类。这个四个实现类,就是 Dubbo 官方提供的负载均衡策略(截止 2.7.7 版本之前),他们分别是:
ConsistentHashLoadBalance 一致性哈希算法
LeastActiveLoadBalance 最小活跃数算法
RandomLoadBalance 加权随机算法
RoundRobinLoadBalance 加权轮询算法
我们已经找到了 LeastActiveLoadBalance 这个类了,那么我们的第二个断点打在哪里已经很明确了。
目前看来,两个断点就可以支撑我们的分析了。
有的朋友可能想问,那我想知道 Dubbo 是怎么识别出我们想要的是最少活跃次数算法,而不是其他的算法呢?其他的算法是怎么实现的呢?从第一个断点到第二个断点直接有着怎样的调用链呢?
在没有彻底搞清楚最少活跃数算法之前,这些统统先记录在案但不予理睬。一定要明确目标,带着一个问题进来,就先把带来的问题解决了。之后再去解决在这个过程中碰到的其他问题。在这样环环相扣解决问题的过程中,你就慢慢的把握了源码的精髓。这是我个人的一点看源码的心得。供诸君参考。
3、模拟环境
既然叫做最小活跃数策略。那我们得让现有的三个消费者都有一些调用次数。所以我们得改造一下服务提供者和消费者。
服务提供者端的改造如下:
PS:这里以权重为 300 的服务端为例。另外的两个服务端改造点相同。
客户端的改造点如下:
一共发送 21 个请求:其中前 20 个先发到服务端让其 hold 住(因为服务端有 sleep),最后一个请求就是我们需要 Debug 跟踪的请求。
运行一下,让程序停在断点的地方,然后看看控制台的输出:
▲上下滑动查看更多
http://www.taodudu.cc/news/show-1505575.html
相关文章:
- Scikit-Learn 学得如何?程序员不容错过十大实用功能来袭
- Scikit-Learn 十大实用功能来袭!
- 从病毒到“基础软件污染”,Linux 真的安全吗?
- 认知智能,AI 的下一个十年 | AI Procon 2020
- 1块钱,能买来财富自由吗?
- 多个线程“打架抢夺”同一个资源,该如何让它们安分?
- 47 张图带你 MySQL 进阶
- 业界首发|云原生领域首本架构白皮书重磅发布
- 新基建东风下,程序员这样乘风破浪!
- 性能 1.84 倍于 Ceph!网易数帆开源分布式存储系统 Curve
- 蚂蚁上市或诞生近60位亿万富翁;特斯拉回应25万元团购Model3;Python 3.8.5 发布| 极客头条
- Python 实现信息自动配对爬虫排版程序
- 七月最后一波!微软专属内推码等你来抢
- 3年出货5000万颗!国内老牌芯片商用平头哥玄铁处理器研发新芯片
- 斯坦福教授亲自上课!字节跳动夏令营超硬核课程实践项目等你来战
- 微信回应“取消两分钟内删除功能”;甲骨文裁撤北京中心;Redis 6.0.6 发布| 极客头条
- 用 AI 培养孩子学习兴趣,讯飞新一代智能学习机正式发布!
- 华为云郑叶来:优势挡不住趋势,技术创新是主旋律
- 云原生带来的云安全机遇
- AR 圈最大收购案 Ubimax 10 亿“卖身”背后:究竟什么才是真正值钱的东西?
- Nature 子刊重磅:腾讯与钟南山团队发布新冠危重症 AI 预测模型 Cox
- 美团推出外卖版拼多多;iOS 14 Beta 3暂禁用3D Touch功能;Rust 1.45 发布| 极客头条
- 发布了!2020 年 AI 人才发展报告,最高补助 1000 万!
- 疫情之下 SaaS 市场两极分化,SaaS 厂商如何突围严峻形势?
- TensorFlow 2.0 发布以来,又有哪些最新进展?| AI ProCon 2020
- 太慢不能忍,CPU 拿硬盘和网卡开刀了!
- Dubbo to Mesh 云原生架构改造方案解析
- 苹果:App Store中国区无版号游戏8月1日起下架;美国计划打造量子互联网;HHVM 4.67 发布 | 极客头条...
- “刚毕业1年,做Python能挣多少?”网友:吹的不多...
- 电磁感应理论之父,法拉第传奇
2 万字长文盘点五种负载均衡策略相关推荐
- 2万字长文盘点五种负载均衡策略
来源:why公众号 荒腔走板 老规矩,在技术分享开始之前,先荒腔走板,聊点别的.给枯燥的技术文章注入一抹其它的色彩. 上面的图片,是我在骑车的过程中拍的.衣服随意的绑在驼包上,两侧各挂着一只鞋子,左边 ...
- 经过负载均衡图片加载不出来_吐血输出:2万字长文带你细细盘点五种负载均衡策略。...
Dubbo的五种负载均衡策略 2020 年 5 月 15 日,Dubbo 发布 2.7.7 release 版本.其中有这么一个 Features 新增一个负载均衡策略. 熟悉我的老读者肯定是知道的, ...
- 吐血输出:2万字长文带你细细盘点五种负载均衡策略。
Dubbo的五种负载均衡策略 2020 年 5 月 15 日,Dubbo 发布 2.7.7 release 版本.其中有这么一个 Features 新增一个负载均衡策略. 熟悉我的老读者肯定是知道的, ...
- SpringCloud Ribbon中的7种负载均衡策略!
作者 | 磊哥 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而 ...
- Nginx的6种负载均衡策略
Nginx的6种负载均衡策略[轮询/加权轮询weight/ip_hash/least_conn/urlhash/fair] 总结:nginx负载均衡策略 1.轮询策略 轮询策略其实是一个特殊的加权策略 ...
- Spring Cloud Ribbon 中的 7 种负载均衡策略
负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者--客户端负载均衡器. 服务端负载均衡器的问题是,它提供了更强的流量控制权,但 ...
- DNS负载均衡与NGINX负载均衡策略
负载均衡是指的是把请求均匀的分摊到多个服务器上处理.一般常见的负载均衡有两种:①客户端与反向代理服务器之间的DNS负载均衡②反向代理服务器与应用服务器之间的负载均衡(这种负载均衡有很多,可以是webl ...
- Nginx服务器之负载均衡策略(6种)
一.关于Nginx的负载均衡 在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器. 二.Nginx负载均衡策略 负载均 ...
- 【Nginx】Nginx服务器之负载均衡策略(6种)
一.关于Nginx的负载均衡 在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器. 二.Nginx负载均衡策略 负载均 ...
最新文章
- 百度拿不到Big Data资源,7h删抓紧时间!!
- DL-5 深度学习框架的对比
- 几个必知的python小知识
- 互联网泛娱乐直播安全的解决之道
- python对excel表格操作
- 不同符号的两个整数求余和取模的计算技巧(规律)
- bootstrap精简教程
- Java小白必看:开发一个编程项目的完整流程(附100套Java编程项目源码+视频)
- OpenCV学习:找出人脸,同时比较两张图片中的人脸相似度
- INTEL 傲腾16G 的再利用
- iOS开发 - 搜索(模糊搜索 支持拼音检索 首字母等)
- Qt 使用-自定义菜单栏
- html:checkbox无法uncheck
- 模型推荐丨新闻传播大数据项目案例模型分享
- git add出现 “fatal: in unpopulated submodule XXX“ 错误
- ESL3.5 学习笔记(主成分回归,偏最小二乘回归步骤详解)
- Apache Flink fault tolerance源码剖析(六)
- 目标检测20年综述之(一)
- 零点极点传递函数以及伯德图
- 基于JAVA客服管理系统计算机毕业设计源码+数据库+lw文档+系统+部署