当前位置: 首页 > news >正文

Spring Cloud中负载均衡器概览

在上篇文章中(RestTemplate的逆袭之路,从发送请求到负载均衡)我们完整的分析了RestTemplate的工作过程,在分析的过程中,我们遇到过一个ILoadBalancer接口,这个接口中有一个chooseServer方法是我们选择服务实例的方法,这个也是整个负载均衡中最最核心的部分,那么它到底是采用了什么样的策略从服务提供者列表中选出了一个服务供服务消费者去调用的?这是我们今天要讨论的问题,本文我主要是想基于互联网上公开的资料,来对Spring Cloud中提供的负载均衡器做一个简明扼要的介绍。


本文是Spring Cloud系列的第八篇文章,了解前七篇文章内容有助于更好的理解本文:

1.使用Spring Cloud搭建服务注册中心
2.使用Spring Cloud搭建高可用服务注册中心
3.Spring Cloud中服务的发现与消费
4.Eureka中的核心概念
5.什么是客户端负载均衡
6.Spring RestTemplate中几种常见的请求方式
7.RestTemplate的逆袭之路,从发送请求到负载均衡


负载均衡器

首先我们来看一张上篇文章中的旧图:

图片描述

这是ILoadBalancer接口的一张类关系图,我们就从这张图里看起吧。

AbstractLoadBalancer

AbstractLoadBalancer类的定义如下:

public abstract class AbstractLoadBalancer implements ILoadBalancer {
    
    public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP        
    }
    public Server chooseServer() {
        return chooseServer(null);
    }
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    public abstract LoadBalancerStats getLoadBalancerStats();    
}

关于这个类我说以下几点:
1. AbstractLoadBalancer实现了ILoadBalancer接口,但它是一个抽象类,它里边定义了一个关于服务实例的分组枚举类,包含了三种类型的服务:ALL表示所有服务,STATUS_UP表示正常运行的服务,STATUS_NOT_UP表示下线的服务。
2. chooseServer方法毫无疑问是用来选取一个服务实例,但是要怎么选这里并没有说,我们以后在它的实现类里边寻找选取策略。
3. getServerList方法用来获取某一个分组中所有的的服务实例。
4. getLoadBalancerStats方法用来获取LoadBalancerStats对象,LoadBalancerStats对象中保存了每一个服务的所有细节信息。

BaseLoadBalancer

BaseLoadBalancer是AbstractLoadBalancer的一个实现类,源码比较长我就不贴出来的,我们在这里主要来说说BaseLoadBalancer提供了哪些功能:

1. 首先这个类中有两个List集合中放的Server对象,一个List集合用来保存所有的服务实例,还有一个List集合用来保存当前有效的服务实例。
2. BaseLoadBalancer中定义了一个IPingStrategy,用来描述服务检查策略,IPingStrategy默认实现采用了SerialPingStrategy实现,SerialPingStrategy中的pingServers方法就是遍历所有的服务实例,一个一个发送请求,查看这些服务实例是否还有效,如果网络环境不好的话,这种检查策略效率会很低,如果我们想自定义检查策略的话,可以重写SerialPingStrategy的pingServers方法。
3. 在BaseLoadBalancer的chooseServer方法中(负载均衡的核心方法),我们发现最终调用了IRule中的choose方法来找到一个具体的服务实例,IRule是一个接口,在BaseLoadBalancer它的默认实现是RoundRobinRule类,RoundRobinRule类中采用了最常用的线性负载均衡规则,也就是所有有效的服务端轮流调用。
4. 在BaseLoadBalancer的构造方法中会启动一个PingTask,这个PingTask用来检查Server是否有效,PingTask的默认执行时间间隔为10秒。
5. markServerDown方法用来标记一个服务是否有效,标记方式为调用Server对象的setAlive方法设置isAliveFlag属性为false。
6. getReachableServers方法用来获取所有有效的服务实例列表。
7. getAllServers方法用来获取所有服务的实例列表。
8. addServers方法表示向负载均衡器中添加一个新的服务实例列表。

BaseLoadBalancer的功能大概就这么多。

DynamicServerListLoadBalancer

DynamicServerListLoadBalancer是BaseLoadBalancer的一个子类,在DynamicServerListLoadBalancer中对基础负载均衡器的功能做了进一步的扩展,我们来看看。

1. 首先DynamicServerListLoadBalancer类一开始就声明了一个变量serverListImpl,serverListImpl变量的类型是一个ServerList<T extends Server>,这里的泛型得是Server的子类,ServerList是一个接口,里边定义了两个方法:一个getInitialListOfServers用来获取初始化的服务实例清单;另一个getUpdatedListOfServers用于获取更新的服务实例清单。
2. ServerList接口有很多实现类,DynamicServerListLoadBalancer默认使用了DomainExtractingServerList类作为ServerList的实现,但是在DomainExtractingServerList的构造方法中又传入了DiscoveryEnabledNIWSServerList对象,查看源码发现最终两个清单的获取方式是由DiscoveryEnabledNIWSServerList类来提供的。
3. DomainExtractingServerList类中的obtainServersViaDiscovery方法是用来发现服务实例并获取的,obtainServersViaDiscovery方法的主要逻辑是这样:首先依靠EurekaClient从服务注册中心获取到具体的服务实例InstanceInfo列表,然后对这个列表进行遍历,将状态为UP的实例转换成DiscoveryEnabledServer对象并放到一个集合中,最后将这个集合返回。
4. DynamicServerListLoadBalancer中还定义了一个ServerListUpdater.UpdateAction类型的服务更新器,Spring Cloud提供了两种服务更新策略:一种是PollingServerListUpdater,表示定时更新;另一种是EurekaNotificationServerListUpdater表示由Eureka的事件监听来驱动服务列表的更新操作,默认的实现策略是第一种,即定时更新,定时的方式很简单,创建Runnable,调用DynamicServerListLoadBalancer中updateAction对象的doUpdate方法,Runnable延迟启动时间为1秒,重复周期为30秒。
5. 在更新服务清单的时候,调用了我们在第一点提到的getUpdatedListOfServers方法,拿到实例清单之后,又调用了一个过滤器中的方法进行过滤。过滤器的类型有好几种,默认是DefaultNIWSServerListFilter,这是一个继承自ZoneAffinityServerListFilter的过滤器,具有区域感知功能。即它会对服务提供者所处的Zone和服务消费者所处的Zone进行比较,过滤掉哪些不是同一个区域的实例。

综上,DynamicServerListLoadBalancer主要是实现了服务实例清单在运行期间的动态更新能力,同时提供了对服务实例清单的过滤功能。

ZoneAwareLoadBalancer

ZoneAwareLoadBalancer是DynamicServerListLoadBalancer的子类,ZoneAwareLoadBalancer的出现主要是为了弥补DynamicServerListLoadBalancer的不足。由于DynamicServerListLoadBalancer中并没有重写chooseServer方法,所以DynamicServerListLoadBalancer中负责均衡的策略依然是我们在BaseLoadBalancer中分析出来的线性轮询策略,这种策略不具备区域感知功能,这样当需要跨区域调用时,可能会产生高延迟。ZoneAwareLoadBalancer重写了setServerListForZones方法,该方法在其父类中的功能主要是根据区域Zone分组的实例列表,为负载均衡器中的LoadBalancerStats对象创建ZoneStats并存入集合中,ZoneStats是一个用来存储每个Zone的状态和统计信息。重写之后的setServerListForZones方法主要做了两件事:一件是调用getLoadBalancer方法来创建负载均衡器,同时创建服务选择策略;另一件是对Zone区域中的实例清单进行检查,如果对应的Zone下已经没有实例了,则将Zone区域的实例列表清空,防止节点选择时出现异常。

OK,以上就是我们对负载均衡器的一个简单介绍,下一篇文章我们将继续介绍负载均衡策略

更多JavaEE资料请关注公众号:

图片描述

以上。。

相关文章:

  • 文件特殊权限:SUID,SGID,SBIT
  • 11.03 在外链接中用OR逻辑
  • 将文件名从1变为000001
  • 重构之美-跨越Web标准,触碰语义网[分离:通用也许是个美丽陷阱]
  • shell脚本(1)
  • 笔记-Kotlin学习
  • 【Unity Shader】五、Shader纹理映射,及纹理的缩放和偏移
  • img 样式单和属性
  • 统计学基于SPSS贾俊平 授课笔记 发布作业 spss19cn 软件下载地址及破解包spss19_10039 下载地址...
  • zabbix监控模板大全
  • 2017杭州云栖大会—移动云专场【赠票】
  • seaJS源码
  • apache 日志轮询三种方法
  • Django REST框架-基于类的视图
  • 玩转算法面试:(三)LeetCode数组类问题
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • [deviceone开发]-do_Webview的基本示例
  • bootstrap创建登录注册页面
  • C++11: atomic 头文件
  • CODING 缺陷管理功能正式开始公测
  • CSS居中完全指南——构建CSS居中决策树
  • docker-consul
  • JavaScript标准库系列——Math对象和Date对象(二)
  • Java编程基础24——递归练习
  • Java新版本的开发已正式进入轨道,版本号18.3
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Sass Day-01
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 利用jquery编写加法运算验证码
  • 七牛云假注销小指南
  • 如何设计一个微型分布式架构?
  • 无服务器化是企业 IT 架构的未来吗?
  • 鱼骨图 - 如何绘制?
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • #传输# #传输数据判断#
  • $.ajax()参数及用法
  • (1)Android开发优化---------UI优化
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (三)c52学习之旅-点亮LED灯
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET Remoting学习笔记(三)信道
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • @requestBody写与不写的情况
  • @Responsebody与@RequestBody
  • @SentinelResource详解
  • [IE技巧] IE8中HTTP连接数目的变化
  • [JS入门到进阶] 前端开发不能写undefined?这是误区!
  • [MYSQL]mysql将两个表结果合并到一起
  • [NOI 2016]循环之美
  • [Oh My C++ Diary]return 1和return 0的区别
  • [POJ 1915] Knight Moves
  • eltable刷新整个表格方法_分析网页 JavaScript Bundles 的几种方法
  • python filedialog打开的对话框啥呀没有_MessageDialog在FileDialog ShowMod之后没有响应
  • python逗号运算符_python正则表达式去掉数字中的逗号(python正则匹配逗号)
  • java计算二叉树的节点最小值_LeetCode算法系列 111. 二叉树的最小深度
  • UVa 575 / ZOJ 1712 / Mid-Central USA 1997 Skew Binary (water ver.斜二进制)
  • js 装饰器_Midway 1.0正式发布:Node.js写法Java化
  • mysql plus root_MySQL 5.7.9 重置root密码
  • cocos入门6:动作系统
  • UVa 10008 What's Cryptanalysis? (water ver.)
  • mysql3.2_3.2-Mysql登陆