源码解析-Eureka Client(二)
1、Eureka Sever解析入口分析
(1)关于Marker实例
通过Eureka Server的依赖我们从spring.factories中找到EurekaServer的自动配置类。
该配置类具有一个条件注解:要求必须要有一个EurekaServerMarkerConæ guration.Marker实例这个配置类才会起作用。那么这个实例是在哪里创建的呢?
打开这个注解,其是一个复合注解,该注解中导入了一个类EurekaServerMarkerConæ gration。打开这个类,可以看到该类是一个配置类,在其中创建了Marker实例。
这就是为什么在EurekaServer启动类上必须添加@EnableEurekaServer注解的原因。
(2)重要实例的创建
2、处理Client状态修改请求
- 修改了注册表中该instanceInfo的status
- 将新的状态记录到了overriddenInstanceStatusMap缓存中
- 将本次修改记录到了recentlyChangedQueue缓存中
3、处理客户端删除overridden状态请求
- 将指定Client的overriddenStatus从overriddenInstanceStatusMap中删除
- 修改注册表中该Client的status为UNKNOWN
- 将本次修改写入到recentlyChangedQueue缓存
- 注意,并没有将该Client从注册表中进行删除
4、处理客户端续约请求
5、Server间的数据同步
注意:变更配置文件时,会提交注册请求。
6、处理客户端下架请求
对比处理删除overridden状态请求与下架请求
处理删除overridden状态请求完成的主要任务:
- 从缓存map中删除指定client的overriddenStatus
- 修改注册表中该client的overriddenStatus为UNKNOWN
- 修改注册表中该client的status为UNKNOWN
- 将本次操作记录到recentlyChangedQueue
- 修改注册表中该client的lastUpdatedTimestamp
处理下架请求完成的主要任务:
- 将该client从注册表中删除
- 从缓存map中删除指定client的overriddenStatus
- 将本次操作记录到recentlyChangedQueue
- 修改注册表中该client的lastUpdatedTimestamp
(蓝色字体为区别)
7、处理客户端注册请求
问题:为什么处理注册请求,写操作加读锁。处理续约时,写操作不加读锁?
问题:如何保证AP?
this.numberOfRenewsPerMinThreshold = (int) (expectedNumberOfClientsSendingRenews * (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds()) * serverConfig.getRenewalPercentThreshold()) = (客户端数量 * (60 / 心跳间隔)*自我保护开启的阈值因子) = (客户端数量 * 每个客户端每分钟发送心跳的数量 * 阈值因子) = (所有客户端每分钟发送的心跳数量 * 阈值因子) =当前Server开启自我保护机制的每分钟最小心跳数量
一旦自我保护机制开启了,那么就将当前Server保护了起来,即当前server注册表中的所有client均不会过期,即当client没有指定时间内(默认90秒)发送续约,也不会将其从注册表中删除。为什么?就是为了保证server的可用性,即保证AP。
expectedNumberOfClientsSendingRenews设置的越大,当前Server开启自我保护机制的每分钟最小心跳数量就越大,就越容易发生自我保护。
8、处理客户端全量下载请求
获取负载源码:
8.1 问题1
readWriteCacheMap中的数据从哪里来?
8.2 问题2
readOnlyCacheMap的数据来自于readWriteCacheMap,但readWriteCacheMap中的数据若发生了变更,那么readOnlyCacheMap中的数据一定也需要发生变化,那么readOnlyCacheMap中的数据在最里发生的变更?
答:在ResponseCacheImpl构造器中定义并开启了一个定时任务,用于定时从readWriteCacheMap中更新readOnlyCacheMap中的数据。
8.3 问题3
为什么不直接从readWriteCacheMap中获取数据,而是从readOnlyCacheMap获取?即这种方案的好处是什么?
答:为了保证对readWriteCacheMap的迭代稳定性。即将读写进行了分离,分离到了两个共享集合。但这种解决方案存在一个很严重的弊端:读、写两个集合的数据无法保证强一致性,即只能做到最终一致性。所以这种方案的应用场景是,对数据的实时性要求不是很高,对数据是否是最新数据要求不高。
9、处理客户端增量下载请求
整体流程同“全量下载”大致相同