前两篇文章分析了 Directory
和 Router
,本文继续分析第三个部分 LoadBalance
的实现。
回顾一下 AbstractClusterInvoker
中的 invoke
方法:
|
|
这里通过 SPI
获取了一个 loadBalance
对象,关于 SPI
的分析将在以后的文章展开,这里先知道这里只是通过将要调用的服务名称来获取一个 loadBalance
实例即可。
在 doInvoke
方法执行中,会调用 AbstractClusterInvoker
中的 select
方法:
|
|
这里会调用 loadBalance
的 select
方法。我们先看下 LoadBalance
的类图:

负载均衡策略
主要有4个实现类来实现不同的负载均衡策略。看下官网的描述:
Random LoadBalance
- 随机,按权重设置随机概率。
- 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
- 轮循,按公约后的权重设置轮循比率。
- 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
- 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
- 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
- 一致性 Hash,相同参数的请求总是发到同一提供者。
- 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
- 算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
- 缺省只对第一个参数 Hash,如果要修改,请配置
<dubbo:parameter key="hash.arguments" value="0,1" />
- 缺省用 160 份虚拟节点,如果要修改,请配置
<dubbo:parameter key="hash.nodes" value="320" />
代码分析
权重的计算
AbstractLoadBalance
是 LoadBalance
接口的默认实现抽象类,我们来看看此类具体的实现:
|
|
可以看到,这里的 select
方法会调用具体由子类来实现的 doSelect
方法,另外比较重要的是 getWeight
方法,用来计算 invoker
的权重。下面分析一下 getWeight
方法,看下具体权重的值是怎么计算的。
该方法有如下几个变量:
- weight:权重,默认是100;
- uptime:
invoker
运行的时间,也就是当前的时间 -invoker
启动的时间; - warmup:
invoker
预热时间,默认是10分钟。
即当 invoker
运行时间小于10分钟,则需要计算权重,运行时间大于10分钟,权重就是设置的值,默认是100。
看下权重的计算:
|
|
计算规则很简单,即: 运行时间 / ( 预热时间 / 权重 )
,也就是说当 invoker
运行时间小于10分钟时, invoker
的运行时间越长,其权重越高。
RandomLoadBalance
dubbo默认的是 Random LoadBalance
,看下 RandomLoadBalance
中的 doSelect
方法:
|
|
这个规则很简单,循环遍历获取每个 invoker
的权重,如果权重一样,也就是 sameWeight
为 true
,那么就随机选取一个 invoker
,否则就会按照权重来选取。
RoundRobinLoadBalance
|
|
这里注意 doSelect
中按权重轮询的部分:
- 第一个
for
循环将循环次数设置为maxWeight
,因为最大的权重就是maxWeight
,所以遍历完之后肯定会有一个Invoker
满足条件并返回; - 第二个
for
循环遍历,当对应的Invoker
的权重大于0的时候,也就是IntegerWrapper
对象的getValue
大于0的时候就将mod
和对应的value
,即invoker
对应的权重,都减一,如果到最后mod
为0的时候如果invoker
对应的权重大于0,则分配到该invoker
。
最后,如果权重都是相同的,则直接取模就可以了。
LeastActiveLoadBalance
该种方式思路主要是,获取最小的活跃数,把活跃数等于最小活跃数的 invoker
维护成一个数组,如果权重一致随机取出,如果不同则跟 RandomLoadBalance
一致,累加权重,然后随机取出,实现如下:
|
|
这里代码的最后一段,其实与 RandomLoadBalance
的实现是一致的。
ConsistentHashLoadBalance
在dubbo中,默认的虚拟节点是160,一致性哈希的算法我后续会介绍,大家也可以参考其他的文章来了解一下这个算法。