0%

eureka原理解析

一、Server启动原理

  1. springboot会去加载META-INF下面的spring.factories自动装配org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration这个类

  1. 此类的判断条件注解标识需要有Mark这个类存在才会加载

  2. 而启动类加上@EnableEurekaServer时,会加载Mark类,从而使自动配置类生效,所以当我们需要使用eureka-server时,必须要在启动类加上此注解

二、Eureka Sever缓存

1.三级缓存

1.1(ConcurrentHashMap)registry

1
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 、端口、属性等。

1.2 ReadOnlyMap(ConcurrentHashMap)

周期更新,类ResponseCacheImpl成员变量,默认每30s从readWriteCacheMap更新

​ ReadOnlyMap是一个只读缓存,供客户端获取注册信息时使用,默认情况下,定时任务每30s将readWriteCacheMap同步至readOnlyCacheMap,通过和 readWriteCacheMap 的值做对比,如果数据不一致,则以 readWriteCacheMap 的数据为准。

1.3 readWriteCacheMap(guava#LoadingCache)

实时更新,类AbstractInstanceRegistry成员变量

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

​ 定时器每60s清理超过90s未续约的节点。

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

2. 缓存机制

2.1 注册一个服务实例

​ 向注册表中写入服务实例信息,并使得readWriteCacheMap缓存失效

2.2 寻找一个服务

​ 从ReadOnlyMap缓存中找,如果有则返回,如果没有则去ReadWriteMap缓存拿并更新,如果ReadWriteMap缓存已经失效,触发guava的回调函数从注册表中同步。

2.3 数据同步定时器

​ 默认情况下定时任务每30s将readWriteCacheMap同步至readOnlyCacheMap,每60s清理超过90s未续约的节点,Eureka Client每30s从readOnlyCacheMap更新服务注册信息,而UI则从registry更新服务注册信息。

3. 缓存相关配置

1
2
3
4
5
6
7
8
9
10
eureka:
instance:
lease-renewal-interval-in-seconds: 30 # 客户端向服务端发送心跳(续约)的时间间隔,默认30s
lease-expiration-duration-in-seconds: 90 # 续约到期时间,服务端收到最后一次心跳后等待的时间上限,默认90s,超时剔除服务
server:
enable-self-preservation: false # 心跳保护机制,默认开启,微服务少的情况下关闭,剔除挂掉的节点;微服务多的情况下开启,防止网络抖动节点心跳丢失而被剔除
eviction-interval-timer-in-ms: 1000 # 逐出实例时间,默认60 * 1000(清理无效节点的时间间隔)
renewal-percent-threshold: 0.85 #自我保护机制触发的阈值,默认0.85
use-read-only-response-cache: false #Client是否从readOnlyCacheMap更新数据,false则跳过readOnlyCacheMap直接从readWriteCacheMap更新,默认true
response-cache-update-interval-ms: 1000 # readwrite 和readOnly 同步时间间隔,默认30 * 1000

4. 多级缓存的优点

​ 尽可能保证了内存注册表中的数据不会出现频繁的读写冲突问题,进一步保证了对eurekaServer的大量请求,都是快速读取内存,提供性能

5. 优化eureka服务端

1
2
3
4
5
6
7
eureka:
server:
enable-self-preservation: false # 心跳保护机制,默认开启,自我保护机制,服务可用数量少于85%时默认开启自我保护机制,不会再剔除服务微服务少的情况下关闭,剔除挂掉的节点;微服务多的情况下开启,防止网络抖动节点心跳丢失而被剔除
eviction-interval-timer-in-ms: 1000 # 逐出实例时间,默认60 * 1000(清理无效节点的时间间隔)
renewal-percent-threshold: 0.85 #自我保护机制触发的阈值,默认0.85
use-read-only-response-cache: false #是否使用从readOnly读取注册表,默认true,三级缓存机制保证高可用,但是一致性减弱了
response-cache-update-interval-ms: 1000 # readwrite 和readOnly 同步时间间隔,默认30 * 1000

三 、Eureka Client缓存

1. 介绍

​ Eureka Client存在两种角色:服务提供者服务消费者,作为服务消费者一般配合Ribbon(Feign内部使用Ribbon)使用。

​ Client启动后,作为服务提供者立即向Server注册,默认情况下每30s续约(renew);作为服务消费者立即向Server全量更新服务注册信息,默认情况下每30s增量更新服务注册信息;Ribbon延时1s向Client获取使用的服务注册信息,默认每30s更新使用的服务注册信息,只保存状态为UP的服务。

2. 二级缓存

2.1 localRegionApps(Eureka Client缓存)

1
private final AtomicReference<Applications> localRegionApps = new AtomicReference<Applications>();

周期更新,类DiscoveryClient成员变量,Eureka Client保存服务注册信息,启动后立即向Server全量更新,默认每30s增量更新

2.2 upServerListZoneMap(ConcurrentHashMap,Ribbon缓存)

周期更新,类LoadBalancerStats成员变量,Ribbon保存使用且状态为UP的服务注册信息,启动后延时1s向Client更新,默认每30s更新

3. 缓存相关配置

1
2
3
4
5
eureka:
instance:
lease-renewal-interval-in-seconds: 30 # 客户端向服务端发送心跳(续约)的时间间隔,默认30s
client:
registry-fetch-interval-seconds: 30 #表示eureka客户端间隔多久去拉取服务注册信息,默认30s,如果要迅速获取服务注册状态,可以减小该值