Eureka架构
数据存储结构
Eureka的数据结构分为:数据存储层(比作MySQL)和二级缓存层(比作Redis)。
数据存储层
registry 本质上是一个双层的ConcurrentHashMap,存储在内存中的。
- 第一层Map的key是
spring.application.name
,value 是第二层 ConcurrentHashMap; - 第二层 ConcurrentHashMap 的 key 是服务的 InstanceId,value 是 Lease 对象;
- Lease 对象包含了服务详情和服务治理相关的属性;
二级缓存层
Eureka 实现了二级缓存来保存对外传输的服务信息,数据结构完全相同。
- 一级缓存(只读缓存):ConcurrentHashMap<Key,Value> readOnlyCacheMap,保存服务信息的对外输出数据结构。
- 二级缓存(读写缓存):Loading<Key,Value> readWriteCacheMap,本质就是Guava Cache本地缓存(LoadingCache),包含失效机制,保存服务信息的对外输出数据结构。
规则
- 服务启动时会生成服务的基本信息对象InstanceInfo,并register到服务治理中心;
- 注册完成后会从服务治理中心拉取所有的服务信息,缓存在本地;
- 之后服务会被30s(可配置)发送一个心跳信息,续约服务;
- 如果服务治理中心在90s内没有收到一个服务的续约,就会认为服务已经挂了,会把服务注册信息删掉;
- 服务停止前,服务会主动发送一个停止请求,服务治理中心会删除这个服务的信息;
- 如果Eureka Server收到的心跳包不足正常值的85%(可配置)就会进入自我保护模式,在这种模式下,Eureka Server不会删除任何服务信息;
- ReadWriteMap与registry的数据是实时一致的(因为有注册后让ReadWriteMap失效的机制),但是ReadWriteMap与ReadOnlyMap不是实时一致的。
缓存更新机制
删除读写缓存
- Eureka Client 发送
register
、renew
和cancel
请求并更新 registry 注册表之后,删除读写缓存; - Eureka Server 自身的
Evict Task
剔除服务后,删除二级缓存; - 读写缓存本身设置了guava的失效机制,隔一段时间后自己自动失效;
Evict Task
定时任务的时间配置是:eureka.server.eviction-interval-timer-in-ms
;
加载读写缓存:
- Eureka Client 发送
getRegistry
请求后,如果读写缓存中没有,就触发 guava 的 load,即从registry中获取原始服务信息后进行处理加工,再加载到读写缓存中。 - Eureka Server 更新只读缓存的时候,如果读写缓存没有数据,也会触发 guava 的 load。
更新只读缓存:
- Eureka Server 内置了一个
TimerTask
,定时将读写缓存中的数据同步到只读缓存(包括删除和加载); TimerTask
这个定时任务的时间配置是:eureka.server.responseCacheUpdateInvervalMs
;