当前位置: 首页 > 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数组类问题
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 2019年如何成为全栈工程师?
  • Angular Elements 及其运作原理
  • canvas 绘制双线技巧
  • ES学习笔记(12)--Symbol
  • github从入门到放弃(1)
  • HTML-表单
  • iOS编译提示和导航提示
  • Node项目之评分系统(二)- 数据库设计
  • Redis在Web项目中的应用与实践
  • Sass Day-01
  • select2 取值 遍历 设置默认值
  • sublime配置文件
  • 阿里研究院入选中国企业智库系统影响力榜
  • 关于使用markdown的方法(引自CSDN教程)
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • ​queue --- 一个同步的队列类​
  • # 达梦数据库知识点
  • #1014 : Trie树
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (2.2w字)前端单元测试之Jest详解篇
  • (AngularJS)Angular 控制器之间通信初探
  • (四)c52学习之旅-流水LED灯
  • (转)Oracle存储过程编写经验和优化措施
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .a文件和.so文件
  • .htaccess 强制https 单独排除某个目录
  • .java 9 找不到符号_java找不到符号
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET面试题(二)
  • @Bean注解详解
  • [《百万宝贝》观后]To be or not to be?
  • [<MySQL优化总结>]
  • [Android]常见的数据传递方式
  • [Angular] 笔记 20:NgContent