写点什么

【Spring Cloud 2】注册中心 Eureka,java 架构面试题 spring 原理

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:3618 字

    阅读完需:约 12 分钟

三、自我保护机制




默认请款下,如果 Eureka Server 在 90 秒内没有接收到某个微服务实例的心跳,会注销该实例。但是在微服务架构下服务之间通常都是跨进程调用,网络通信往往面临很多问题,比如微服务状态正常,网络分区故障,导致此实例被注销。


固定时间内大量实例被注销,可能会严重威胁某个微服务架构的可用性,为了解决这个问题,Eureka 开发了自我保护机制,那么什么是自我保护机制呢?


Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 即进入自我保护机制。


Eureka Server 触发自我保护机制后,页面会出现提示:



Eureka Server 进入自我保护机制,会出现以下几种情况:


(1)Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。


(2)Eureka 仍然能够接受新服务的注册和查询,但是不会被同步到其它节点上(即保证当前节点依然可用)。


(3)当网络稳定后,当前实例新的注册信息会被同步到其它节点上。


Eureka 自我保护机制是为了防止误杀服务而提供的一种机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。


如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一无效的服务实例,则会调用失败。对于这个问题需要服务消费者要有一些容错机制,比如重试,断路器等。


四、Eureka 高可用集群




理论上来讲,服务消费者本地缓存了服务提供者的地址,即使 Eureka Server 宕机,也不会影响服务之间的调用,但是一旦涉及到服务的上下线,本地的缓存信息将会出现偏差,影响整个微服务的稳定性,因此搭建 Eureka Server 集群来提高整个架构的高可用性,是非常必要的。



从图中可以看出 Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册提高可用性,每个节点需要添加一个或多个有效的 serviceURL 指向其他节点。


如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点。当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行节点间复制,将请求复制到其它 Eureka Server 当前所知的所有节点中。


另外 Eureka Server 的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。所以,如果存在多个节点,只需要将节点之间两两连接起来形成通路,那么其它注册中心都可以共享信息。每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过 P2P 的方式完成服务注册表的同步。


Eureka Server 集群之间的状态是采用异步方式同步的,所以不保证节点间的状态一定是一致的,不过基本能保证最终状态是一致的。


五、?Eureka 分区




Eureka 提供了 Region 和 Zone 两个概念来进行分区:


Region:可以理解为地理上的不同区域,比如亚洲地区,中国地区,大连地区等等。没有具体大小的限制。根据项目具体的情况,可以自行合理划分 Region。


Zone:可以简单理解为 region 内的具体机房,比如说 region 划分为大连,大连有两个机房,就可以再次 region 之下划分出 zone1,zone2 两个 zone。


六、Eureka 保证 AP




Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。


七、Eureka 工作流程




1、Eureka Server 启动成功,等待服务端注册。


在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息。


2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务。


3、Eureka Client 会每 30 秒向 Eureka Server 发送一次心跳,证明客户端服务正常。


4、当 Eureka Server90 秒内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例。


5、单位时间内 Eureka Server 统计到大量的 Eureka Client 没有发送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有发送心跳的客户端。


6、当 Eureka Client 心跳恢复正常后,Eureka Server 自动退出自我保护机制。


7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存在本地。


8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存。


9、Eureka Client 获取到目标服务器信息,发起服务调用。


10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中剔除。



八、?Eureka??Server 数据存储




Eureka??Server 的数据存储分为两层:数据存储层和缓存层。


数据存储层记录注册到?Eureka??Server 上的服务信息,缓存层是经过包装后的数据,可以直接在?Eureka??Client 调用时返回。


Eureka??Server 的数据存储层是双层的 ConcurrentHashMap,我们知道?ConcurrentHashMap??是线程安全高效的 Map 集合。


private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry= new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();


第一层的 ConcurrentHashMap 的 key=spring.application.name 也就是客户端实例注册的应用名;value 为嵌套的 ConcurrentHashMap。


第二层嵌套的 ConcurrentHashMap 的 key=instanceId 也就是服务的唯一实例 id,value 为 Lease 对象,Lease 对象存储着这个实例的所有注册信息,包括 IP、端口、属性等。


根据这个存储结构我们可以发现,Eureka Server 第一层都是存储着所有的服务名,以及服务名对应的实例信息,也就是说第一层都是按照服务应用名这个维度来切分存储:


应用名 1:应用 1 实例 Map


应该名 2:应用 2 实例 Map


...


第二层是根据实例的唯一 ID 来存储的,那么按照这个结构最终的存储数据格式为:


: 应用 1 实例 A:实例 A 的注册信息


应用名 1:应用 1 实例: 应用 1 实例 B:实例 B 的注册信息


: 应用 1 实例 C:实例 C 的注册信息


: ....




: 应用 2 实例 F:实例 F 的注册信息


应该名 2:应用 2 实例: 应用 2 实例 G:实例 G 的注册信息


: ...


...


数据存储层数据结构如下图所示:



当如服务的状态发生变更时,会同步 Eureka Server 中的 registry 数据信息,比如服务注册、剔除服务时。


九、?Eureka 的缓存机制




E


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ureka Server 为了提供响应效率,提供了两层的缓存结构,将 Eureka Client 所需要的注册信息,直接存储在缓存结构中。


第一层缓存:readOnlyCacheMap,本质上是 ConcurrentHashMap,依赖定时从 readWriteCacheMap 同步数据,默认时间为 30 秒。


readOnlyCacheMap?: 是一个?CurrentHashMap 的只读缓存,这个主要为了供客户端获取注册信息时使用,其缓存更新,依赖于定时器的更新,通过和?readWriteCacheMap?的值做对比,如果数据不一致,则以?readWriteCacheMap?的数据为准。


第二层缓存:?readWriteCacheMap?,本质上是 Guava 缓存。


readWriteCacheMap:readWriteCacheMap??的数据主要同步于存储层。当获取缓存时判断缓存中是否没有数据,?如果不存在此数据,则通过 CacheLoader 的 load 方法去加载,加载成功之后将数据放入缓存,同时返回数据。


readWriteCacheMap 缓存过期时间,默认为 180 秒,当服务下线、过期、注册、状态变更,都会来清除此缓存中的数据。


Eureka Client 获取全量或者增量的数据时,会先从一级缓存中获取;如果一级缓存中不存在,再从二级缓存中获取;如果二级缓存也不存在,这时候先将存储层的数据同步到缓存中,再从缓存中获取。


通过 Eureka Server 的二层缓存机制,可以非常有效地提升 Eureka Server 的响应时间,通过数据存储层和缓存层的数据切割,根据使用场景来提供不同的数据支持。


十、代码实例



1、项目架构

2、Eureka 服务端 application.yml

server:


port: 9000


eureka:


instance:


hostname: localhost


client:


register-with-eureka: false


fetch-registry: false


service-url:


defaultZone: http://{server.port}/eureka/


instance:


prefer-ip-address: true

3、客户端启动类

package cn.itcast.product;


...


@SpringBootApplication


@EntityScan("cn.itcast.product.entity")


@EnableEurekaClient


public class ProductServiceApplication {


public static void main(String[] args) {


SpringApplication.run(ProductServiceApplication.class, args);


}


}


4、一些基本的 controller、service、bean 就不写了,使用的是 spring data jpa 方式查询的数据库。

5、启动服务

Eureka Server -->?Eureka Providor -->?Eureka Consumer

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
【Spring Cloud 2】注册中心Eureka,java架构面试题spring原理