Soul网关源码探秘《十》 - 负载均衡 - Hash/RoundRobin
前文分析了DividePlugin
插件中负载均衡的总体结构以及Random
的具体实现。今天来探索剩下两种负载均衡是如何实现的。
准备工作
见Soul网关源码探秘《八》 - 负载均衡初探
Hash
找到具体实现类HashLoadBalance
直接查看
public DivideUpstream doSelect(final List<DivideUpstream> upstreamList, final String ip) {// 1. 遍历服务列表,为每个服务在生成 VIRTUAL_NODE_NUM 条(默认为5条)的 hash-服务 记录,放入一个有序 treemap 存放for (DivideUpstream address : upstreamList) {for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {long addressHash = hash("SOUL-" + address.getUpstreamUrl() + "-HASH-" + i);treeMap.put(addressHash, address);}}// 2. 使用参数 ip 生成一个 hash 值long hash = hash(String.valueOf(ip));// 3. 在 treemap 中找出 key 比 hash 大的所有记录SortedMap<Long, DivideUpstream> lastRing = treeMap.tailMap(hash);if (!lastRing.isEmpty()) {// 4. 返回符合条件的第一条记录return lastRing.get(lastRing.firstKey());}// 5. 如果没有 key 比 hash 大的记录,则返回 treemap 中的第一条记录return treeMap.firstEntry().getValue();}
可以看到,在 hash 算法中,并没有使用到权重值参与到计算中。
看完还有以下两个问题有点懵:
- 没有看懂这样实现负载均衡有啥优势?
- 怎么保证转发更加平均?
RoundRobin
找到RoundRobinLoadBalance
查看具体实现:
public DivideUpstream doSelect(final List<DivideUpstream> upstreamList, final String ip) {// ...// 1. 每次接收到请求的总权重int totalWeight = 0;long maxCurrent = Long.MIN_VALUE;// ...for (DivideUpstream upstream : upstreamList) {// ...// 2. 每一个服务中维护一个积累值,积累值每次增加的值为该服务的权重值long cur = weightedRoundRobin.increaseCurrent();// ...// 3. 如果当前服务积累值大于 maxCurrent,则选择该服务;继续下一次循环if (cur > maxCurrent) {maxCurrent = cur;selectedInvoker = upstream;selectedWRR = weightedRoundRobin;}// 4. 总权重增加totalWeight += weight;}// 5. 没搞懂这一部分是会在什么情况下触发;以及有什么用处?if (!updateLock.get() && upstreamList.size() != map.size() && updateLock.compareAndSet(false, true)) {try {// copy -> modify -> update referenceConcurrentMap<String, WeightedRoundRobin> newMap = new ConcurrentHashMap<>(map);newMap.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > recyclePeriod);methodWeightMap.put(key, newMap);} finally {updateLock.set(false);}}if (selectedInvoker != null) {// 6. 如果选中某个服务,那么这个服务对应的 cur 减去总权重进入负值阶段,重新开始积累怒气值selectedWRR.sel(totalWeight);return selectedInvoker;}// should not happen herereturn upstreamList.get(0);}
可以看到对应于每一个服务会维护一个该服务的怒气值,RoundRobin算法会经历这两个阶段:
- 每当接收到请求后,每一个服务都会增加相当于自身权重值的怒气值。
- 最终怒气值最高的服务在这一轮胜出,执行转发请求的任务。同时,该服务的怒气值会减去总权重进入负值阶段重新开始积攒怒气值。
例如,现有权重分别为50,100的两个服务。
第一轮的 cur 依次为 50,100。100权重的服务胜出并将 cur 减去总权重。最终得到 cur 为 50,-50(100-150)
第二轮的 cur 依次为 100,50(-50+100)。50权重的服务胜出并将 cur 减去总权重。最终得到 cur 为 -50(100-150),50
第二轮的 cur 依次为 0,150。100权重的服务胜出并将 cur 减去总权重。最终得到 cur 为 0,0(150-150)。如此往复。。。
总结
Random 是每次接收请求都是独立按照各自权重进行计算;
而 RoundRobin 是把过往的每一次都算数。
Soul网关源码探秘《十》 - 负载均衡 - Hash/RoundRobin相关推荐
- Soul网关源码阅读(十)自定义简单插件编写
Soul网关源码阅读(十)自定义简单插件编写 简介 综合前面所分析的插件处理流程相关知识,此次我们来编写自定义的插件:统计请求在插件链中的经历时长 编写准备 首先我们先探究一下,一个P ...
- Soul网关源码解析目录
Soul网关源码解析目录 Soul网关源码解析文章列表 对用Java写的高性能网关:Soul,进行一波学习和研究,下面是相关的文章记录 掘金 了解与初步运行 Soul网关源码解析(一) 概览 ...
- Soul网关源码阅读(九)插件配置加载初探
Soul网关源码阅读(九)插件配置加载初探 简介 今日来探索一下插件的初始化,及相关的配置的加载 源码Debug 插件初始化 首先来到我们非常熟悉的插件链调用的类: SoulWebHa ...
- Soul网关源码阅读(八)路由匹配初探
Soul网关源码阅读(八)路由匹配初探 简介 今日看看路由的匹配相关代码,查看HTTP的DividePlugin匹配 示例运行 使用HTTP的示例,运行Soul-Admin,Sou ...
- Soul网关源码阅读(七)限流插件初探
Soul网关源码阅读(七)限流插件初探 简介 前面的文章中对处理流程探索的差不多了,今天来探索下限流插件:resilience4j 示例运行 环境配置 启动下MySQL和redis d ...
- Soul网关源码阅读番外篇(一) HTTP参数请求错误
Soul网关源码阅读番外篇(一) HTTP参数请求错误 共同作者:石立 萧 * 简介 在Soul网关2.2.1版本源码阅读中,遇到了HTTP请求加上参数返回404的错误,此篇文章基于此进行探索 ...
- Soul 网关源码阅读(六)Sofa请求处理概览
Soul 网关源码阅读(六)Sofa请求处理概览 简介 今天来探索一下Sofa请求处理流程,看看和前面的HTTP.Dubbo有什么异同 Sofa示例运行 PS:如果请求加上参数运行不成功,请更 ...
- Soul网关源码阅读(六)请求类型探索
Soul网关源码阅读(六)请求类型探索 简介 在上几篇文章中分析了请求的处理流程,HTTP和RPC请求处理是互斥的,通过请求类型来判断,这篇文章来探索下请求类型的前世今生 源码分析 通 ...
- Soul 网关源码阅读(四)Dubbo请求概览
Soul 网关源码阅读(四)Dubbo请求概览 简介 本次启动一个dubbo服务示例,初步探索Soul网关源码的Dubbo请求处理流程 示例运行 环境配置 在Soul源码clone下来 ...
最新文章
- Enda 的 2015 下半年读书计划
- 全球及中国汽车空调冷凝器行业发展前景规模及投资战略决策报告2022-2027年
- 剑指offer(21):栈的压入、弹出序列
- ubuntu查看版本
- 【OS学习笔记】二十九 保护模式八:任务切换对应的汇编代码之用户程序代码
- Serverless爆发,前端又一大利好消息
- 文件自动备份和同步bypy和syncthing
- VAX Patch VA_X.DLL 安装位置的问题 for VS2008 , VS2010 , VS2011
- C#经纬度坐标算距离
- POI Excel列宽设置
- CalBioreagents 绵羊抗α-2-HS糖蛋白 亲和纯化说明
- 12 款适用于开发人员的最佳 Web 开发软件
- 用计算机运算符编写检索式,在计算机检索中,常用的布尔逻辑算符有哪几种
- ESP32 开发笔记(三)源码示例 10_IIC_ADXL345 使用IIC总线实现读取ADXL345角度加速度传感器
- cocos 躲避球游戏(1) --创建项目和场景切换
- layui镜像网站分享
- 什么是DBMS以及DBMS的分类
- 软件开发专业需要学习多少年
- elasticsearch搭建遇到的问题整理合集1
- 为什么越来越多明星开始关注加密货币?
热门文章
- HTML表格中包多个CApTion,Html中的table包括 caption、col、colgroup、thead、tfoot 以及 tbody...
- 怎么把位域合成一个字节_C51中位域在字节中的位置关系
- Android 应用访问权限设置
- elementui 隐藏输入框_vue+element-ui实现显示隐藏密码
- C语言的整型和长整型的字节长
- Idea 无法创建Servlet问题
- 431金融带计算机,金融硕士考研:考研金融431能带计算器吗?
- 修改注册表消除应用软件乱码显示(转)
- 使用scrollTop回到顶部时间
- 机会成本---你到底是赚了,还是赔了?