针对dubbo的文章已经很多,

我们这里通过代码的解析,简单描述下各种负载均衡的实现方式

随机负载均衡(RandomLoadBalance:先统计所有服务器上该接口方法的权重总和,然后对这个总和随机nextInt一下,看生成的随机数落到哪个段内,就调哪个服务器上的该服务。

protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
int length = invokers.size(); // 总个数
int totalWeight = 0; // 总权重
boolean sameWeight = true; // 权重是否都一样
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight; // 累计总权重
if (sameWeight && i > 0
&& weight != getWeight(invokers.get(i - 1), invocation)) {
sameWeight = false; // 计算所有权重是否一样
}
}
if (totalWeight > 0 && ! sameWeight) {
// 如果权重不相同且权重大于0则按总权重数随机
int offset = random.nextInt(totalWeight);
// 并确定随机值落在哪个片断上
for (int i = 0; i < length; i++) {
offset -= getWeight(invokers.get(i), invocation);
if (offset < 0) {
return invokers.get(i);
}
}
}
// 如果权重相同或权重为0则均等随机
return invokers.get(random.nextInt(length));
}

轮询负载均衡( RoundRobinLoadBalance ): 如果所有服务器的该接口方法的权重一样,则直接内部的序列计数器( sequences ) +1 然后对服务器的数量进行取模来决定调用哪个服务器上的服务;如果服务器的该接口方法的权重不一样(就是说存在预热中的服务器),则找到其中最大的权重,然后将内部的权重计数器( weightSequences ) +1 并对该最大权重数取模,然后再找出权重比该取模后的值大服务器列表,最后通过内部的序列计数器( sequences ) +1 然后对服务器列表数量进行取模来决定调用哪个服务器上的服务。

  protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
int length = invokers.size(); // 总个数
int maxWeight = 0; // 最大权重
int minWeight = Integer.MAX_VALUE; // 最小权重
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
maxWeight = Math.max(maxWeight, weight); // 累计最大权重
minWeight = Math.min(minWeight, weight); // 累计最小权重
}
if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样
AtomicPositiveInteger weightSequence = weightSequences.get(key);
if (weightSequence == null) {
weightSequences.putIfAbsent(key, new AtomicPositiveInteger());
weightSequence = weightSequences.get(key);
}
int currentWeight = weightSequence.getAndIncrement() % maxWeight;
List<Invoker<T>> weightInvokers = new ArrayList<Invoker<T>>();
for (Invoker<T> invoker : invokers) { // 筛选权重大于当前权重基数的Invoker
if (getWeight(invoker, invocation) > currentWeight) {
weightInvokers.add(invoker);
}
}
int weightLength = weightInvokers.size();
if (weightLength == 1) {
return weightInvokers.get(0);
} else if (weightLength > 1) {
invokers = weightInvokers;
length = invokers.size();
}
}
AtomicPositiveInteger sequence = sequences.get(key);
if (sequence == null) {
sequences.putIfAbsent(key, new AtomicPositiveInteger());
sequence = sequences.get(key);
}
// 取模轮循
return invokers.get(sequence.getAndIncrement() % length);
}

最少活跃负载均衡( LeastActiveLoadBalance :每个接口和接口方法都对应一个 RpcStatus 对象,记录了他们的活跃数、失败数等等相关统计信息,此种负载均衡方式是在活跃数最低的服务器中对其权重的总和取模来看结果是在哪个权重段中,则选择该服务器来调用,活跃数就像并发量降级中的计数器一样,开始调用时活跃数 +1 ,调用结束时活跃数 -1 ,所以活跃值越大,表明该提供者服务器的该接口方法耗时越长,而消费能力强的提供者接口往往活跃值很低。最少活跃负载均衡保证了“慢”提供者能接收到更少的服务器调用。

 protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {int length = invokers.size(); // 总个数int leastActive = -1; // 最小的活跃数int leastCount = 0; // 相同最小活跃数的个数int[] leastIndexs = new int[length]; // 相同最小活跃数的下标int totalWeight = 0; // 总权重int firstWeight = 0; // 第一个权重,用于于计算是否相同boolean sameWeight = true; // 是否所有权重相同for (int i = 0; i < length; i++) {Invoker<T> invoker = invokers.get(i);int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // 活跃数int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // 权重if (leastActive == -1 || active < leastActive) { // 发现更小的活跃数,重新开始leastActive = active; // 记录最小活跃数leastCount = 1; // 重新统计相同最小活跃数的个数leastIndexs[0] = i; // 重新记录最小活跃数下标totalWeight = weight; // 重新累计总权重firstWeight = weight; // 记录第一个权重sameWeight = true; // 还原权重相同标识} else if (active == leastActive) { // 累计相同最小的活跃数leastIndexs[leastCount ++] = i; // 累计相同最小活跃数下标totalWeight += weight; // 累计总权重// 判断所有权重是否一样if (sameWeight && i > 0 && weight != firstWeight) {sameWeight = false;}}}// assert(leastCount > 0)if (leastCount == 1) {// 如果只有一个最小则直接返回return invokers.get(leastIndexs[0]);}if (! sameWeight && totalWeight > 0) {// 如果权重不相同且权重大于0则按总权重数随机int offsetWeight = random.nextInt(totalWeight);// 并确定随机值落在哪个片断上for (int i = 0; i < leastCount; i++) {int leastIndex = leastIndexs[i];offsetWeight -= getWeight(invokers.get(leastIndex), invocation);if (offsetWeight <= 0)return invokers.get(leastIndex);}}// 如果权重相同或权重为0则均等随机return invokers.get(leastIndexs[random.nextInt(leastCount)]);}

一致哈希负载均衡( ConsistentHashLoadBalance ): 一致性哈希算法的负载均衡保证了同样的请求(参数)将会落到同一台服务器上,这在某些场景是非常有用的, Dubbo 中默认采用了 160 个虚拟节点,因为 Dubbo 的请求 URL 中除了我们使用的参数,还有些额外的系统调用参数,比如 timestamp 、 loadbalance 、 pid 和 application 等,有人可定会问, Dubbo 会对 URL 中哪些参数进行 hash , Dubbo 默认除了对我们接口所有参数进行 hash 外,还会加上这些额外参数

 protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();int identityHashCode = System.identityHashCode(invokers);ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);if (selector == null || selector.getIdentityHashCode() != identityHashCode) {selectors.put(key, new ConsistentHashSelector<T>(invokers, invocation.getMethodName(), identityHashCode));selector = (ConsistentHashSelector<T>) selectors.get(key);}return selector.select(invocation);}

dubbo的轮询机制说明相关推荐

  1. 【状态保持】Cache 基于SQL 数据库 的缓存依赖 轮询机制详解

    首先声明一下如果您还不了解什么是Cache(缓存)请您先搜一下有关信息然后再看这篇文章. 当数据库中的信息发生变化的时候,应用程序能够获取变化的通知是缓存依赖得以实现的基础.应用程序可以通过两种途径获 ...

  2. (原创)Linux设备轮询机制分析

    一. 设备轮询机制的基本思想 所谓的设备轮询机制实际上就是利用网卡驱动程序提供的NAPI机制加快网卡处理数据包的速度,因为在大流量的网络环境当中,标准的网卡中断加上逐层的数据拷贝和系统调用会占用大量的 ...

  3. MCDF中arbiter的轮询机制

    更新的MCDF的仲裁器采用的是Round Robin轮询的一个仲裁机制,简单来说就是最先被授权的通道在下一次仲裁中优先级会变为最低,这样可以保证每个通道都能够获得授权,而不是一个通道长时间连续的进行数 ...

  4. 码支付如何对接网站_第四方聚合支付特色之一的轮询机制是怎么防风控的?

    简单地说,聚合支付是融合了支付宝.微信支付.花呗.翼支付等多种支付方式的一种"包容性"支付工具.做支付系统一定不能脱离实际业务场景,更不能照搬其他公司方案. 做聚合支付的服务商越来 ...

  5. android全局轮询机制,Android轮询机制

    在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一 ...

  6. Node中的事件轮询机制

    文章目录 2 node中的事件循环模型 2-1 一些属性 2-2 循环模型 node事件循环总共有==六个阶段== process.nextTick()函数 __实例__ 2 node中的事件循环模型 ...

  7. 轮询机制php,JS事件轮询机制讲解

    JS是单线程语言,深入理解JS里的Event Loop,本文主要和大家分享JS事件轮询机制,希望能帮助到大家. JS的执行机制(一): 1.首先判断JS是同步还是异步,同步就进入主进程,异步就进入ev ...

  8. STM32基于时间片轮询机制

    1. 基于时间片的轮询调度算法(仅局限单核CPU芯片): 利用定时器为每个任务函数设定执行时间间隔,保证使用频率高的函数多次被调用,提高单核芯片的资源利用率.如果只是简单地将A.B两个函数放在whil ...

  9. NGINX轮询机制的几种形式

    前言:总以为轮询就简单的next而已,实际还有几种不同的实现机制.某个客户的源站有几个不同的IP,回源的时候自然是采用的轮询的机制.客户业务上线前,检查源站的联通性发现一个漏网之鱼竟然差点滥竽充数.然 ...

最新文章

  1. python中参数(带星号的参数)
  2. 【测试点分析】1060 爱丁顿数 (25分)_21行代码
  3. linux系统支持u盘格式,linux下U盘格式化
  4. flex里播放声音的方法
  5. Java基础知识框图总结
  6. 跟bWAPP学WEB安全(PHP代码)--SSL(Server-Side-Include)漏洞
  7. 【图文教程】Windows给Rabbitmq安装rabbitmq_delayed_meaage_exchange
  8. java案例代码19--二分查找排序
  9. 复选框选中的值怎么传到mysql_PHP中如何将复选框选中的内容提交到mysql的一个字段中...
  10. 结构体变量偏移量及大小计算
  11. vc2008不安装vcredist发布程序
  12. PC微信多开源代码-消息钩子+ZwQuerySystemInformation
  13. 图文详解VxLAN技术(二)
  14. leapftp连接不上,为什么leapftp连接不上
  15. 一文教你高效画出技术架构图
  16. 《JavaScript》条件运算符
  17. visio 2010 技巧
  18. 如何在本地进行一个IP访问多个域名
  19. Java多态实现人喂养宠物小案例
  20. 小程序tab选项卡请求我的订单数据筛选处理(待收货、代发货、已完成等)

热门文章

  1. Glide的源码解析(一)(附方法调用图)
  2. AI观察|机器人成为了我们的好伙伴,你愿意吗?
  3. TCP协议三次握手和四次挥手
  4. PCF8591芯片以及AD学习(一)
  5. 使用PV操作描述售票大厅
  6. 随机验证码和短信验证
  7. 数字孪生水电站,三维组态助力发电流程优化
  8. 前端开发面试经验之苏宁
  9. 基于深度学习的GAN应用风格迁移
  10. Java 中Pair的认识