写点什么

注册中心

作者:邱学喆
  • 2022 年 2 月 20 日
  • 本文字数:2809 字

    阅读完需:约 9 分钟

注册中心

一. 概述

在微服务架构中必不可少的一个组件,将所有的应用服务器信息都收集到注册中心,便于其他应用服务器去做负载以及减少配置工作量。

二. 功能点

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 列表。该算法是:

quarantineSet记录访问失败的endpoint列表1. quarantineSet与cluster_endpoints的交集,重新放入到quarantineSet集合中;2. 如果quarantineSet的数量为空,则直接返回cluster_endpoints3. 如果quarantineSet.size/cluster_endpoints>=0.66(默认值),	则清理quarantineSet,并直接返回cluster_endpoints4. 否则,从cluster_endpoints中找出不在quarantineSet集合的元素列表。
复制代码
  • RedirectingEurekaHttpClient 主要是重定向处理

  • ClusterResolver 的接口的实现类

  • AsyncResolver 异步获取 clusterEndpoints,其实现原理是通过定时器去拉取

  • ZoneAffinityClusterResolver 将 clusterEndpoints 进行按照当前客户端所在的 region 与其他 region 分开,自己所在的 region 放到前面,其他 region 放到后面

  • ApplicationsResolver 找到本地的服务列表中的 vip 地址的运行实例信息,接着封装成目标对象

  • EurekaHttpResolver 向远程发起获取 vip 的实例信息,接着封装成目标对象;

  • ConfigClusterResolver 直接从配置文件中获取,

1. 从当前节点配置的region区获取有效的zone列表2. 设置自己的zone,也就是zone列表中的第一个,如果zone列表为空,则默认为default3. 然后遍历serviceUrl,优先把自己所在zone的endpoint放到最前面;
复制代码

从 DiscoverClient 类中对网络的初始化过程,使用了哪些上述的实现类。

网络传输流转,如图所示:

4.3.2 服务端

服务端有一篇介绍的很详细,SpringCloud-Eureka原理解析。具体可以看其介绍。下面只是对其关键的部分以及图进行摘抄而已。

数据存储


核心逻辑

  • 每次客户端向服务端的发送数据操作的,都会异步的同步到其他节点。至于其他节点信息,是来自配置文件指定的列表以及定时任务来更新的,具体的代码 PeerEurekaNodes 类可以找到相关逻辑。

  • 定时清除过期的修改事件,AbstractInstanceRegistry.getDeltaRetentionTask

  • 定时剔除无效的服务 EvictionTask-> AbstractInstanceRegistry.evict

  • 定时更新续约门槛(RenewalThreshol)PeerAwareInstanceRegistryImpl.updateRenewalThreshold

#更新续约机制1. 获取本地的服务注册数count2. 如果count > 期望指定客户端续约数(expectedNumberOfClientsSendingRenews)*0.85(默认值,可以配置)如果条件为真,则进入第三步3. 更新操作3.1 更新expectedNumberOfClientsSendingRenews = count3.2 更新自我保护值(numberOfRenewsPerMinThreshold) = expectedNumberOfClientsSendingRenews * 2 * 0.85
复制代码
  • 定时更新缓存 ResponseCacheImpl.getCacheUpdateTask

  • 服务获取机制

region&zone

总结

后续完善

引用

  1. SpringCloud-Eureka原理解析

  2. Eureka Server启动过程分析

  3. Eureka 配置参数说明

发布于: 刚刚阅读数: 2
用户头像

邱学喆

关注

计算机原理的深度解读,源码分析。 2018.08.26 加入

在IT领域keep Learning。要知其然,也要知其所以然。原理的爱好,源码的阅读。输出我对原理以及源码解读的理解。个人的仓库:https://gitee.com/Michael_Chan

评论

发布
暂无评论
注册中心