dubbo解析-负载均衡LoadBalance四大实现类算法原理详解

本文基于dubbo 2.7.5版本代码

dubbo的负载均衡可以分为两个方面,一个是对多注册中心的负载均衡,一个是对多服务的负责均衡。dubbo的负载均衡类继承关系图如下:
继承关系图,引用:https://www.cnblogs.com/wyq178/p/9822731.html

一、负载均衡权重计算规则

dubbo提供了负载均衡算法很多都需要计算权重,因此先说明权重的计算规则。
在org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance#getWeight方法里面,对权重进行了计算,计算过程涉及到两个参数:uptime和warmup。

  • uptime=当前系统时间-服务端服务发布时间,该字段表示截止到现在服务运行了多久;
  • warmup是服务端配置的,表示服务需要的预热时间,该参数需要配置到spring配置文件中,如下:dubbo.provider.warmup=10000,服务端所有的服务预热时间都是这个值,单位是毫秒。

权重计算
从上图可以看出,权重默认是100,权重最小是0,。如果服务端配置了预热时间warmup,且当前服务端还在预热期内,那么权重需要等比例的调低,权重=(已启动时间/预热时间)*权重。

二、负载均衡LoadBalance实现类算法详解

下面介绍一下负载均衡各个实现类的功能。每个负载均衡实现类都需要实现doSelect方法,该方法的入参invoks表示所有可用服务的List集合。

1、RandomLoadBalance

这是使用随机算法的负载均衡,如果每个服务的权重相同,使用代码返回对应服务下标,也就是入参invoks的下标:

ThreadLocalRandom.current().nextInt(length)

length表示服务总个数。
如果权重不同,选择服务的方式如下:
在这里插入图片描述
假如有五个服务,每个服务的权重为:服务S1权重100,服务S2权重200,服务S3权重140,服务S4权重230,服务S5权重300,计算出的offset=364。那么选中的服务是364-S1-S2-S3<0,所以选择服务S3。

2、RoundRobinLoadBalance

该类相当于轮询算法。当所有的服务提供者权重相同时,会按照入参invoks集合从下标0开始顺次遍历使用每个服务提供者。但是当权重不同时,遍历的顺序会有所不同。

在该类中使用了对象WeightedRoundRobin,WeightedRoundRobin记录每个服务提供者的当前权重weight、历史权重current和最后一次遍历时间lastUpdate。其中历史权重current初始化为0,每次访问服务提供者前,都会变更current=current+weight。
在这里插入图片描述
WeightedRoundRobin对象记录了服务最后一次遍历时间lastUpdate,如果发现一个服务的最后一次遍历时间与现在间隔了超过了60000毫秒,那么该服务对应的WeightedRoundRobin对象会被销毁。

该算法经历了多次修改,最新版本是2.7.5,该版本的算法是参考了Nginx。具体内容参见官网:

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

3、LeastActiveLoadBalance

该类是最小活跃数负载均衡,该算法认为活跃数越小,说明服务响应速度越快,自然被调用的概率越大。使用该负载均衡算法需要启用过滤器ActiveLimitFilter,在ActiveLimitFilter过滤器中对活跃数增减。

最小活跃数使用类RpcStatus记录,该类中有个常量METHOD_STATISTICS,记录每个服务提供者对应的RpcStatus对象,RpcStatus对象的active属性即是服务提供者的活跃数。
在这里插入图片描述
当选出了所有的活跃数最小的服务后,然后使用RandomLoadBalance的算法,从这些服务中选出一个服务返回。

ActiveLimitFilter过滤器用于修改活跃数,当时客户端发起一次调用时,会增加1,服务端调用返回后,活跃数再减1。所以在多线程环境下,服务提供者被多次同时调用,在服务提供者返回前,这些提供者的活跃数都不为0,如果某个提供者的响应速度非常快,那么其活跃数相比较来说比较小。默认ActiveLimitFilter过滤器不会被启用,我们需要配置actives属性(actives表示允许最大并发调用数),比如:使用注解@Reference(actives=10)。

4、ConsistentHashLoadBalance

该类使用一致性哈希算法,该类也是唯一一个忽略了权重和预热时间的算法。网上介绍一致性哈希算法的原理的文章很多,本文不在做介绍。

该类的流程是:
在这里插入图片描述

上述流程图中涉及到两个参数hash.nodes和hash.arguments。设置这两个参数的注解配置方式是:@Reference(parameters={“hash.nodes”,“320”,“hash.arguments”,“1,2”}),该注解的含义是hash.nodes=320,hash.arguments=1,2。

  • hash.arguments:当调用远程服务时根据服务请求的哪几个参数生成key,并根据key来通过一致性hash算法来选择调用节点。默认是0,也就是第一个请求参数,如果要选取多个参数,中间用逗号分隔,比如:“1,2,3”。假如入参为args[5],hash.arguments=1,2,那么上图中计算请求值的md5=md5(args[1].toString()+args[2].toString())
  • hash.nodes:为虚拟节点的副本数。默认是160,也就是说每个服务在圆环上存在160个虚拟节点。

一致性哈希算法中的圆环使用TreeMap表示。

如果远程服务没有请求参数,例如calAccount(),那么在入参Invokers集合不变的前提下,任何对远程服务的调用都一直返回相同的服务提供者Invoker。

源代码解析可以参考下面两篇文章:

http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html
https://www.cnblogs.com/wyq178/p/9822731.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值