注册中心
一. 概述
在微服务架构中必不可少的一个组件,将所有的应用服务器信息都收集到注册中心,便于其他应用服务器去做负载以及减少配置工作量。
二. 功能点
2.1 服务注册
当应用服务启动时,就会向注册中心上报应用服务器的相关信息。一般包括如下信息
主机名
IP 地址
端口号
协议信息
应用名称
当然还有其他特性的信息,如应用名称归属组,以及服务器所归属机房信息等。
2.2 心跳检测
应用服务上报后,需要时时监控应用的运行情况,那么就需要检测机制,来确保信息的准确性(注册中心的服务器信息列表是可用的)。
这里的心跳检测,有两种方式:
应用服务器周期上报信息,从而注册中心定时去更新。
注册中心定时向应用服务发起心跳检测,来检查应用服务是否下线。
2.3 服务发现
既然收集到了应用服务器,必然会提供给应用服务器去拉取它感兴趣的服务器列表。以便于应用服务器拿到服务器列表再做进一步处理,也就是说负载处理。
2.4 总结
从上面介绍的功能点介绍,里面有三种角色存在。
应用消费者
应用提供者
注册中心
其粗糙的交互图如下:
三. 高可用
上面的交互图是最简单的,我们再进一步进行梳理。注册中心的高可用的设计方案。
高可用的设计方案依然逃不过 CAP 理论,具体 CAP 理论。具体可网络查找答案,或者参考《分布式事务与分布式系统》,所以在做高可用的设计方案时,往往注重 AP,而不是 CA 或 CP 等模式。因为数据一致性在注册中心的重要程度没有其他两个因素更加重要。
3.1 中心化
中心化,意味着提供一个统一入口,让消费者和提供者去访问。
提供统一入口,必然需要一个选举组件,来选出一个主节点来充当门面,让所有请求都流转到这个门面来;
有关虚拟 IP 的实现原理,可以参考《虚拟IP技术原理》
又或者是
客户端配置集群中的所有节点,交由客户端去轮询集群节点,找到可以访问的节点去进行远程调用。
当然还有其他方案,这里就不在列举出来了。
那么基于中心化的设计方案,必然依赖于选举组件。一般来说,选举组件都是基于数据最新的节点作为主节点。
3.2 去中心化
去中心化,意味着所有节点都可以提供服务能力。客户端按照一定的算法选择可以可以访问的节点进行远程。常规方案如下:
但去中心化有一个问题,那就是各个节点的数据不一定是一致的,但最终会一致,不会出现大多问题。
四. Eureka
在 spring cloud 全家桶中,注册中心我们所使用的是 Eureka。Eureka 的集群架构是去中心化的,也就是基于 AP 模式。
4.1 概念
region 可以理解为地理上的分区,如华南地区,华北地区等概念,
zone 可以理解为 region 下的具体机房,如北京机房,西安机房等。
服务续约 即应用提供者会定期的向 eureka 服务发送心跳,来告知“i am still alive“的信息,以防止 eureka 服务将该应用服务从服务列表剔除出去。
服务下线 即应用提供者下线后,会向 eureka 服务发送消息,来告知”i will offline“的信息,让 eureka 服务将该应用从服务列表剔除出去。
4.2 特性
Eureka 实现了上述的三个功能,并且拓展了其他特性,特性如下:
服务粒度的细分
自我保护机制
4.3 源码解析
4.3.1 客户端
消费者
当 DiscoveryClient 初始化时和定时向远程拉取服务列表,流程图如下
我们看一下 fetchRegistry 的逻辑,如图:
refreshRegistry 方法的逻辑,比较简单,就是判断当前拉取的分区于配置中指定的 region 分区比对,如果不一样,则强制拉取所有服务列表,否则拉取增量的服务列表。然而从代码层面来看,基本不会触发强制拉取所有服务列表。个人感觉这个是个 bug,不应该是固定指定配置的值,而是根据网络的情况,来动态修改 region。《???》
提供者
启动时向 eureka 注册服务
当 spring 容器启动过程中,抛出 WebServerInitializedEvent 或者 RefreshScopeRefreshedEvent 事件时,会向 eureka 服务发送心跳,具体过程如下:
最后注册的代码如下:
又或者是 DiscoveryClient 初始化时,判断配置中是否向 eureka 注册,如果是,则向远程 eureka 注册:
定时向 eureka 发送心跳,流程如下
网络传输
EurekaHttpClient 接口的实现类
SessionedEurekaHttpClient 从代码上来看,为了避免客户端一直连接固定的 eureka server。所以周期的会将连接给关闭,重新发起连接。
RetryableEurekaHttpClient 当远程访问异常时,会进行重试。当指的注意的是,每次重试就会选择下一个 endpoint。而服务器列表是由 ClusterResolver 接口来获取集群 endpoint 列表。经过一定的算法,来选择候选的 endpoint 列表。该算法是:
RedirectingEurekaHttpClient 主要是重定向处理
ClusterResolver 的接口的实现类
AsyncResolver 异步获取 clusterEndpoints,其实现原理是通过定时器去拉取
ZoneAffinityClusterResolver 将 clusterEndpoints 进行按照当前客户端所在的 region 与其他 region 分开,自己所在的 region 放到前面,其他 region 放到后面
ApplicationsResolver 找到本地的服务列表中的 vip 地址的运行实例信息,接着封装成目标对象
EurekaHttpResolver 向远程发起获取 vip 的实例信息,接着封装成目标对象;
ConfigClusterResolver 直接从配置文件中获取,
从 DiscoverClient 类中对网络的初始化过程,使用了哪些上述的实现类。
网络传输流转,如图所示:
4.3.2 服务端
服务端有一篇介绍的很详细,SpringCloud-Eureka原理解析。具体可以看其介绍。下面只是对其关键的部分以及图进行摘抄而已。
数据存储
核心逻辑
每次客户端向服务端的发送数据操作的,都会异步的同步到其他节点。至于其他节点信息,是来自配置文件指定的列表以及定时任务来更新的,具体的代码 PeerEurekaNodes 类可以找到相关逻辑。
定时清除过期的修改事件,AbstractInstanceRegistry.getDeltaRetentionTask
定时剔除无效的服务 EvictionTask-> AbstractInstanceRegistry.evict
定时更新续约门槛(RenewalThreshol)PeerAwareInstanceRegistryImpl.updateRenewalThreshold
定时更新缓存 ResponseCacheImpl.getCacheUpdateTask
服务获取机制
region&zone
总结
后续完善
引用
版权声明: 本文为 InfoQ 作者【邱学喆】的原创文章。
原文链接:【http://xie.infoq.cn/article/7271dcdd5c4651e3406373fde】。文章转载请联系作者。
评论