Eureka注册中心源码解析
2021-02-18 10:45:40 6 举报
登录查看完整内容
Eureka注册中心源码解析
作者其他创作
大纲/内容
null
expectedNumberOfRenewsPerMin每分钟的期望续约次数实例数 * 2
返回 true
初始化计划任务
numberOfRenewsPerMinThreshold每分钟的最小续约次数实例数 * 2 * 0.85
getAndUpdateDelta(applications)
构建server的上下文
initScheduledTasks
Eureka服务端在\"上一分钟实际收到的心跳数\"小于\"每分钟期望的心跳数\"时就会进入自我保护模式
readOnlyCacheMap30秒过期,从readWrite拉取
你的每个服务里,会配置一个eureka server列表,谁配置在第一个,所有的服务优先就是访问那个eureka server。然后如果那台eureka server宕机了,那么此时所有的服务在重试过后都会访问其他的eureka server,而且此后大家都会去访问那台新的eureka server重点,默认走注册列表的第一个重点,默认走注册列表的第一个重点,默认走注册列表的第一个
发送http
hash比对
实例数 * 2 * 0.85,这是期望的心跳数
如果第一次注册失败,那后来还会再进行心跳发送(走第三步)如果注册失败,发送心跳后404,心跳方法中会再发送注册请求
PeerAwareInstanceRegistry注册表
A
创建核心线程数为 2的线程池定时以及周期性执行任务:newScheduledThreadPool
return 期望的一分钟会有多少次的心跳数 > 0&& 实际心跳数 > 实例数 * 2 * 0.85这里其实如果没达到我们的期望心跳数,就进入自我保护,不进行服务剔除
scheduleRenewalThresholdUpdateTask()
监听
初始化 eurekaTransport , 用来发送 http 请求具体实现: AbstractJersey2EurekaHttpClient
检查服务实例\\心跳
从注册表的map中,根据服务名和实例id,获取一个Lease<InstanceInfo>,更新一下lastUpdateTimestamp这个时间戳,每次续约,就更新一下这个时间戳就ok了
DefaultEurekaServerConfig加载 eureka-server.properties 文件中的配置
for 循环剔除实例,循环次数就是可摘除得数量
注册状态变更监听statusChangeListener
isLeaseExpirationEnabled判断是否开启自我保护
D
加载eureka-server.properties的过程(1)创建了一个DefaultEurekaServerConfig对象(2)创建DefaultEurekaServerConfig对象的时候,在里面会有一个init方法(3)先是将eureka-server.properties中的配置加载到了一个Properties对象中,然后将Properties对象中的配置放到ConfigurationManager中去,此时ConfigurationManager中去就有了所有的配置了(4)然后DefaultEurekaServerConfig提供的获取配置项的各个方法,都是通过硬编码的配置项名称,从DynamicPropertyFactory中获取配置项的值,DynamicPropertyFactory是从ConfigurationManager那儿来的,所以也包含了所有配置项的值(5)在获取配置项的时候,如果没有配置,那么就会有默认的值,全部属性都是有默认值的思想:不是通过一大堆的常量类获取配置项的,提供了一个获取配置的接口,接口里包含大量的方法,每个方法可以获取一个配置
创建 【缓存刷新执行器】 监测线程CacheRefreshThread
30 s 拉取
创建一个集群节点
初始化缓存
更新自我保护的心跳值
initRemoteRegionRegistry()
Server
进行client到服务的注册post http:/localhost:8080:/v2/apps/ServiceA InstanceInfo的json信息,就是cleint的信息实例数据对server而言,就知道服务ServiceA对应一个实例,在ip 192.168.2.87 端口11004上
ResponseCacheImpl
其实这里有问题:就是如果我们开启了自我保护,然后心跳不够的话,直接就不进行服务剔除了,有可能是服务都要剔除得,但是直接自我保护的话,服务都不剔除了
不能一次摘除过多的实例。假如现在有 10个实例 ,有四个故障了 但是最多只能摘除10 - 10*0.85 = 2 个
读取client的配置文件
刷新 InstanceInfo.refreshDataCenterInfoIfRequired(); 刷新数据信息.refreshLeaseInfoIfRequired(); 刷新租约信息
puthttp://localhost:8080/v2/apps/ServiceA/i-000000-1
readWrite读取
1、注册client服务实例信息2、封装续约示例 Lease<InstanceInfo> lease2、作废该实例的之前缓存信息 readWriteCacheMap3、新增的实例信息,添加到对应的增量Map中
client 服务注册:discoveryClient.register()
initEurekaEnvironment();
bug:续约时,本来应该记录的是当前时间,但是代码确在当前的时间上加上了续约时间 90 s,也就导致了,真正感知客户端下线的时间就变成了所以服务剔除时间为:90 + 90 + 两次心跳检查的时间差(该线程60秒执行一次,可能因为GC导致不是整整60秒)
replicateToPeers、复制相关的信息推送到其他的server节点
registry.init(peerEurekaNodes)
PeerEurekaNodes#start()
集群信息同步:https://blog.csdn.net/weixin_43496689/article/details/1031820321、初始化定时任务线程池2、初始化集群节点信息 updatePeerEurekaNodes 方法3、初始化固定周期(默认10分钟,可配置)更新集群节点信息的任务的线程4、通过定时任务,线程池定时执行更新集群节点线程
client属性接口EurekaClientConfig
B
ServerCodecs serverCodecs 暂不理解,创建数据流的编码解码器
random.nextInt从expiredLeases 随机摘除
get http://localhost:8080/v2/apps/delta
ApplicationsResourceApplicationResourceInstanceResource#renewLease
是
是否开启自我保护
serverContext.initialize() -- 初始化注册表
然后这里真正就会调用下面的服务注册方法
续约 client30s一次
执行缓存刷新 30秒一次
启动类 EurekaBootStrap # contextInitialized
初始化client
Eureka client的过程类似
N
EvictionTask检查服务下线
Y
集群同步,非实时,500MS
60 s 一次
关于集群数据的同步:正常情况下在启动的时候就会去拉取一次所有的节点信息在正常服务上线、下线也都会进行进群推送但是 有一点,如果是剔除的,这时候只是自己的缓存中清除了,其他的服务节点是不进行同步的,也就是ABC、都自行的心跳去检查D是否down,然后更新各自的缓存
实际心跳数 >实例数 * 2 * 0.85
全量拉取
注册监控
Eureka server
通讯
registry.syncUp() -- 从相邻的server集群节点中拷贝信息,失败则下一个
第一次获取注册表信息。fetchRegistry,全量拉取
server本身也是一个client,注册到其他集群上
初始化 DiscoveryClient
初始化集群注册表
init
applicationInfoManager
先去readOnly读取
get 返回 InstanceInfobuild 建造者模式,封装的是client的注册信息
180 s
集群的节点同步
postInit
返回 false
peerEurekaNodes
EurekaServerContextHolder.initialize(serverContext)
springcloud服务注册时用到
否
DefaultEurekaClientConfig加载 eureka-client.properties 文件中的配置
十分钟?、同步
END
initEurekaServerContext();
遍历所有服务实例的过期时间
增量拉取
get http://localhost:8080/v2/apps
internalCancel
spring cloud Eureka Server 会在这里进行一步事件发布,也就是publishEvent EurekaInstanceCanceledEvent 事件下线
获取所有的服务实例
服务注册新增实例http:/localhost:8080:/v2/apps/ServiceA ApplicationResources -> ApplicationResources # addInstance
AbstractJersey2EurekaHttpClient#register
return true
初始化数据中心、运行环境archaius相关,赞不理解,忽略
创建 【心跳监测执行器】 监测线程HeartbeatThread
合并、hash比对
注册时同步数据信息 (线程异步执行)
这个集群数据同步的任务,会放入一个acceptorQueue里面去,AcceptorRunner后台线程来处理,每隔10ms会执行一次业务逻辑中间有一个打包的过程,他默认会将500ms内的请求,注册、心跳、下线,打成一个batch,再一次性将这个batch发送给其他的机器,减少网络通信的次数,减少网络通信的开销,集群同步的批量处理的机制eureka server集群同步的时效性,基本上是在1s内,几百毫秒都是正常的
30秒一次,拉取的是3分钟内的增量信息
InstanceInfoReplicator.start
服务端server初始化
eurekaClient
暂不理解
eurekaServerConfig
重新计算自我保护的心跳值
1、获取补偿时间、GC相关2、
创建服务注册线程InstanceInfoReplicator
(如果心跳过去,service没有对应的服务信息,返回404,然后client会重新注册)
默认开启
serverContext
getAndStoreFullRegistry()
执行心跳续约 30秒一次
* 0.85
获取 增量的注册信息通过增删改合并本地缓存数据
如果失败,轮询发送
initializedResponseCache()
fetchRegistry,注册表信息拉取拉取注:如果所有的Server的url地址都访问不到,则从本地备份注册表取,(暂时不理解这个备份)
run
初始化clent信息
evict
读取server的配置文件
本地数据合并完成之后,生成hash和增量数据返回的携带的全量hash对比,如果存在差异就再走一次全量拉取
需要剔除得服务实例> 0
自我保护仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。
如果失败,轮询发送,
EurekaMonitors.registerAllStats() -- 注册所有监视统计信息
1、获取所有注册实例数2、计算可剔除得服务实例数 = 实例数 * 0.85 3、通过可剔除得服务实例数和 expiredLeases 过期的服务实例取最小,也就是判断能剔除多少个实例数
1、排除自身2、同步:Cancel 取消下线、Heartbeat 心跳、Register 注册 、StatusUpdate 状态变更、DeleteStatusOverride 删除?被动下线
15分钟一次如果从别的eureka server拉取到的服务实例的数量,大于当前的服务实例的数量,会重新计算一下自我保护需要的心跳值
renew续约更新心跳
start
PeerEurekaNodes : 猜测,集群的节点信息
疑惑:为什么这里不通知其他的集群server下线服务,我觉得应该是下一次Eureka server会过来拉取注册信息,但是又有一句,如果ABC三台集群,D是客户端,这时候A发现有实例D挂了剔除了,然后C去B上拉取得注册信息,这时候是不是就没发现D下线了么 ? 其实不是这样的1、D的每次心跳信息都会发给集群得所有节点,如果A能发现D有问题,其实B也能如果 A独立中断了,但是这时候D又刚好每次心跳都去A发送心跳所以当B去拉取服务得时候,就会从C拉取注册信息,其实这时候可能就会剔除D了这是一个问题么?心跳默认永远发第一个
end
ApplicationsResource #getContainers转到getVelue
注意:recentlyChangedQueue这里返回的是三分钟内的变化实例信息,Registry注册的时候,有一个任务,30秒一次,看一下服务实例的变更记录,是否有变更实例在队列里停留了超过180s(3分钟)
第一步:EurekaHttpClientDecorator # register第三步:RetryableEurekaHttpClient # execute(重点:如果失败轮询注册)
instanceInfoReplicator.onDemandUpdate()
心跳如果404,未发现服务,再调用注册流程的方法
上下文放入holder
发送http请求
Eureka server 端
registry注册表、永不过期
也就是这的每次都是去检查自我保护,而不是一个设置的值,之前以为的是会有一个值去设定,就是可以理解成,60s内都是自我保护状态,下一个60s统计了上一个60S的心跳值,看是否继续开启自我保护
ApplicationInfoManager管理client的注册info信息
registry
注意: 这里的0.85是服务端期望的心跳比
集群同步的时效
DefaultEurekaServerContext() , server上下文信息
默认有40秒的延迟,但是不理解
拷贝注册表
ConfigurationManager属性管理器
server属性接口EurekaServerConfig
注册实例、复制到其他集群节点
PeerAwareInstanceRegistry:可以感知eureka server集群的服务实例注册表PeerAware,可以识别eureka server集群的Peer:集群中的一个实例InstanceRegistry:注册实例,服务实例注册表
X 中断
readWriteCacheMap180秒过期,重新拉一次数据
??????
ApplicationsResource #getContainerDiffretional转到getValue
C
double check + volatile 单例模式
1、设置服务下线2、将该实例添加到修改队列recentlyChangedQueue3、从缓存剔除实例
三层队列的推送, 学习学习 批量。1、添加改变拉取 2分类3、batch 分组,后台程序拉取发送这里有个500毫秒batch 推送 : PeerReplicationResource #batchReplication
初始化client 的info管理器
Eureka client
获取要剔除的实例集合expiredLeases
eurekaClientConfig
0 条评论
回复 删除
下一页