当前位置: 代码迷 >> 综合 >> 【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法
  详细解决方案

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

热度:42   发布时间:2023-09-14 18:44:03.0

持续输出原创文章,点击蓝字关注我吧

这是why技术的第16篇原创文章

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

全文共计7786字,50图,预计阅读15分钟。

本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析。文中所示源码,没有特别标注的地方均为2.6.0版本。

为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两个bug。从bug讲起来,印象更加深刻。

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

本文目录

第一节:Demo准备。

本小节主要是为了演示方便,搭建了一个Demo服务。Demo中启动三个服务端,负载均衡策略均是最小活跃数,权重各不相同。

第二节:断点打在哪?

本小节主要是分享我看源码的方式。以及我们看源码时断点如何设置,怎么避免在源码里面"瞎逛"。

第三节:模拟环境。

本小节主要是基于Demo的改造,模拟真实环境。在此过程中发现了问题,引申出下一小节。

第四节:active为什么是0?

本小节主要介绍了RpcStatus类中的active字段在最小活跃数算法中所承担的作用,以及其什么时候发生变化。让读者明白为什么需要在customer端配置ActiveLimitFilter拦截器。

第五节:剖析源码

本小节对于最小活跃数算法的实现类进行了逐行代码的解读,基本上在每一行代码上加入了注释。属于全文重点部分。

第六节:Bug在哪里?

逐行解读完源码后,引出了2.6.0版本最小活跃数算法的两个Bug。并通过2.6.0/2.6.5/2.7.4.1三个版本的异同点进行交叉对比,加深读者印象。

第七节:意外收获 

看官方文档的时候发现了一处小小的笔误,我对其进行了修改并被merged。主要是介绍给开源项目贡献代码的流程。

PS:前一到三节主要是分享我看源码的一点思路和技巧,如果你不感兴趣可以直接从第四节开始看起。本文的重点是第四到第六节。

另:阅读本文需要对Dubbo有一定的了解。

一.Demo准备

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

这篇文章分享的是Dubbo负载均衡策略之一最小活跃数(LeastActiveLoadBalance)。所以我先搭建一个Dubbo的项目,并启动三个provider供consumer调用。

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

默认权重是多少?后面看源码的时候,源码会告诉你。

三个不同的服务提供者会给调用方返回自己是什么权重的服务。

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

可以看到三个服务提供者分别在20880、20881、20882端口。(每个红框的最后5个数字就是端口号)。

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

二.断点打在哪?

相信很多朋友也很想看源码,但是不知道从何处下手。处于一种在源码里面"乱逛"的状态,一圈逛下来,收获并不大。

这一小节我想分享一下我是怎么去看源码。首先我会带着问题去源码里面寻找答案,即有针对性的看源码。

如果是这种框架类的,正如上面写的,我会先搭建一个简单的Demo项目,然后Debug跟进去看。Debug的时候当然需要是设置断点的,那么这个断点如何设置呢?

第一个断点,当然毋庸置疑,是打在调用方法的地方,比如本文中,第一个断点是在这个地方:

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

接下里怎么办?

你当然可以从第一个断点处,一步一步的跟进去。但是在这个过程中,你发现了吗?大多数情况你都是被源码牵着鼻子走的。本来你就只带着一个问题去看源码的,有可能你Debug了十分钟,还没找到关键的代码。也有可能你Debug了十分钟,问题从一个变成了无数个。

那么我们怎么避免被源码牵着四处乱逛呢?我们得找到一个突破口,还记得我在《很开心,在使用mybatis的过程中我踩到一个坑》这篇文章中提到的逆向排查的方法吗?这次的文章,我再次展示一下该方法。

看源码之前,我们得冷静的分析。目标要十分明确,就是想要找到Dubbo最小活跃数算法的具体实现类以及实现类的具体逻辑是什么。根据我们的provider.xml里面的:

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

很明显,我们知道loadbalance是关键字。所以我们拿着loadbalance全局搜索,可以看到dubbo包下面的LoadBalance。

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

其实现类为:

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

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

同时,到这里。我们知道了LoadBalance是一个SPI接口,说明我们可以扩展自己的负载均衡策略。抽象方法doSelect有四个实现类。这个四个实现类,就是Dubbo官方提供的负载均衡策略,他们分别是:

ConsistentHashLoadBalance 一致性哈希算法 

LeastActiveLoadBalance 最小活跃数算法 

RandomLoadBalance  加权随机算法 

RoundRobinLoadBalance 加权轮询算法

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

目前看来,两个断点就可以支撑我们的分析了。

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

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

三.模拟环境

既然叫做最小活跃数策略。那我们得让现有的三个消费者都有一些调用次数。所以我们得改造一下服务提供者和消费者。

服务提供者端的改造如下:

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

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

客户端的改造点如下(for循环里面的i应该为<20):

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

一共发送21个请求:其中前20个先发到服务端让其hold住(因为服务端有sleep),最后一个请求就是我们需要Debug跟踪的请求。

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

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

【图文并茂】一文讲透Dubbo负载均衡之最小活跃数算法

▲上下滑动查看更多

  相关解决方案