Dubbo 源码分析08 负载均衡算法

Dubbo 源码分析08 负载均衡算法

Dubbo 源码分析08 负载均衡算法

代码@1:根据所有的调用者生成一个HashCode,用该HashCode值来判断服务提供者是否发生了变化。
代码@2:获取服务提供者< dubbo:method/>标签的hash.nodes属性,如果为空,默认为160,表示一致性hash算法中虚拟节点数量。其配置方式如下:

代码@3:一致性Hash算法,在dubbo中,相同的服务调用参数走固定的节点,hash.arguments表示哪些参数参与hashcode,默认值“0”,表示第一个参数。
代码@4:为每一个Invoker创建replicaNumber 个虚拟节点,每一个节点的Hashcode不同。同一个Invoker不同hashcode的创建逻辑为:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2.2 RandomLoadBalance 加权随机算法实现分析

代码@1:首先求所有服务提供者的总权重,并判断每个服务提供者的权重是否相同。
代码@2:如果提供者之间的权重不相同,则产生一个随机数(0-totalWeight),视为offset,然后依次用offset减去服务提供者的权重,如果减去(offset - provider.weight < 0),则该invoker命中。
代码@3:如果服务提供者的权重相同,则随机产生[0-invoker.size)即可。
2.3 RoundRobinLoadBalance 加权轮询算法分析
加权轮询算法的核心算法是按权重轮询,一个基本点是应该是一个当前序号与服务提供者数量取模,需要结合权重。Dubbo使用如下数据结构存储当前序号:

代码@1:构建ConcurrentMap< String, AtomicPositiveInteger> sequences中的key,以interface+methodname为键,里面存储的是当前序号(轮询)。
代码@2:构建LinkedHashMap< Invoker< T>, IntegerWrapper>存储结构,通过遍历所有Invoker,构建每个Invoker的权重,与此同时算出总权重,并且得出所有服务提供者权重是否相同。
代码@3:获取当前的轮询序号,用于取模。
代码@4:如果服务提供者之间的权重有差别,需要按权重轮询,实现方式是:
1)用当前轮询序号与服务提供者总权重取模,余数为mod。
2)然后从0循环直到最大权重,针对每一次循环,按同一顺序遍历所有服务提供者,如果mod等于0并且对应的Invoker的权重计算器大于0,则选择该服务提供者;否则,mod–,invoker对应的权重减一,权重是临时比那里LinkedHashMap< Invoker< T>, IntegerWrapper>。由于外层循环的次数为所有服务提供者的最大权重,内层循环当mod等于0时,肯定会有一个服务提供者的权重计数器大于0,而返回对应的服务提供者。返回的服务提供者是第一个满足的服务提供者,后续的服务提供者在下一次就会有机会, 因为下一次mod会增大1,后续的服务提供者通过轮询会被选择,选择的机会,取决于权重的大小。
代码@5:如果各服务提供者权重相同,则直接对服务提供者取模即可,轮询后递增。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2.4 LeastActiveLoadBalance 最少活跃连接数负载均衡算法分析
最小活跃连接数,其核心实现就是,首先找到服务提供者当前最小的活跃连接数,如果一个服务提供者的服务连接数比其他的都要小,则选择这个活跃连接数最小的服务提供者发起调用,如果存在多个服务提供者的活跃连接数,并且是最小的,则在这些服务提供者之间选择加权随机算法选择一个服务提供者。
代码@1:解释相关局部变量。
length :服务提供者数量。
leastActive :服务提供者的最小活跃连接数,初始化为-1。
leastCount :服务提供者中都是活跃连接数的个数,例如,3个服务提供者当前的活跃连接数分别为 100,102,100,则leastCount 为2。
leastIndexs:存放拥有活跃连接数的Invoker索引,例如上面100,102,100,则leastIndexs[0]=0, leastIndexs[1] = 2;
totalWeight:拥有最小活跃连接数的Invoker的总权重。
firstWeight :第一个最小活跃连接数的Invoker的权重。
sameWeight :拥有最小活跃连接数的Invoker权重是否相同。
代码@2:遍历所有的服务提供者,计算上述变量的值。
代码@3:如果leastActive (最小活跃连接数为-1,表示第一次遍历)或最新连接数大于当前遍历的Invoker的活跃连接数,需要reset如下值,重新计算:
leastActive = active; // Record the current least active value
leastCount = 1; // Reset leastCount, count again based on current leastCount
leastIndexs[0] = i; // Reset
totalWeight = weight; // Reset
firstWeight = weight; // Record the weight the first invoker
sameWeight = true; // Reset, every invoker has the same weight value?
代码@4:如果当前遍历的服务提供者的活跃数等于leastActive ,则将总权重想加,并在leastIndexs中记录服务提供者序号。
代码@5,如果最小活跃连接数的服务提供者数量只有一个,则直接返回该服务提供者。
代码@6,如果最小活跃连接数的服务提供者有多个,则使用加权随机算法选取服务提供者。