eureka整体架构、运行流程及核心机制
2021-11-30 22:31:11 0 举报
eureka整体架构、运行流程及核心机制
作者其他创作
大纲/内容
多级缓存过期机制
心跳续约
定时(30s)发送一次心跳
eureka-server B
batchingDispatcher
将processerQueue队列中的数据分批放入batchWorkQueue中
在服务主动下线后,同步给其他服务端
判断逻辑
创建一个batchExecutors执行期其执行batchWorkQueue取出的batch
加读锁,避免多线程出现并发问题
全量抓取注册表
写入
组装增量量注册表的缓存key
ReplicationTaskProcessor
主动过期
AcceptorExecute
发送心跳
读写缓存readWriteCacheMap
在注册成功后,同步给其他服务端
CacheRefreshThread
从最近变更的注册表队列中获取注册表数据
返回全量注册表
计算一次最多下线的故障实例。1、获取本地注册表的服务实例注册数量(例如:100个)2、计算一个阈值(100 * 0.85 = 85)3、计算一次最多摘除服务实例的数量(100 - 85 = 15)4、再通过服务实例过期的数量与限定一次性最多摘除的服务实例取最小值(例如:当前故障的服务实例是21个,那么本次最多摘除的数量是15个)
使用AbstractJersey2EurekaHttpClient#register方法将当前InstanceInfo信息注册到eureka-server。http://localhost:8080/v2/apps/ServiceA实际调用的是ApplicationResource#addInstance
定时(30s)抓取增量注册表
ApplicationsResource#getContainerDifferential()
增量抓取注册表
使用AbstractJersey2EurekaHttpClient#sendHeartBeat方法到eureka-server心跳续约。http://localhost:8080/v2/apps/serviceA/0000-1实际调用的是InstanceResource#renewLease()
优化
重新注册
将eureka-server的全量注册表信息组装返回
循环注册表,根据isExpired核心方法判断实例是否故障。这里判断故障的时候将补偿时间加到上一次心跳时间。牛逼的地方,就是将时间补偿机制计算出来的时间差值传入,极大的兼容的不可控的时间差问题
HeartbeatThread
180s定时自动过期 读写缓存
累加心跳数(eureka-server一分钟内最小的心跳次数的判断依据)
自动故障感知及实例的自动摘除(60s)
刷新读写缓存
举例
获取偏差时间值(上次故障检测时间-本次故障检测时间-故障检测间隔时间)补偿时间的机制
放入最近变更队列中recentlyChangedQueue
判断shouldUseReadOnlyResponseCache为false
这里硬编码*2有bug,如果我把心跳时间改成10s钟执行一次,那就是有问题的。如果现在有20个实例节点,那么一分钟内期望的心跳次数为: 20 * (60 / 10)= 120次,而不是 20 * 2 = 40次
如果我们配置了关闭eureka-server进入自我保护,,则不需要走下面的逻辑了erueka-server.properties【enableSelfPreservation】
processingOrder
更新最近一次成功心跳的时间戳
获取增量注册表(key的name=ALL_APPS_DELTA)
全量拉取注册表
InstanceInfo设置污点信息,并设置污点时间。当注册完毕时,清除污点信息,保证不会重复注册。
eureka-server A
每隔60s执行一次EvictionTask任务EvictionTask
定时过期
ALL_APPS
ApplicationResource#addInstance
刷新读写缓存(主动过期)invalidateCache
将返回的全量注册表保存到eureka-client本地缓存注册表中
根据eureka-client.properties中的【shouldFetchRegistry】判断是否需要抓取注册表,默认开启
注册
使用AbstractJersey2EurekaHttpClient#getApplicationsInternal方法到eureka-server获取全量注册表。http://localhost:8080/v2/apps/ServiceA实际调用的是ApplicationsResource#getContainers()
AcceptorExecuter去处理注册请求,将当前注册请求放入AcceptorQueue队列中,并计数
将放入acceptorQueue队列的任务放入processingOrder队列
自我保护机制
bug
ALL_APPS_DELTA
放入最近变更队列中
eureka-client由DiscoveryClient实现
30s定时过期
只读缓存readOnlyCacheMap
使用AbstractJersey2EurekaHttpClient#getApplicationsInternal方法到eureka-server获取增量注册表。http://localhost:8080/v2/apps/delta实际调用的是ApplicationsResource#getContainerDifferential
更新最近一次心跳时间(当前时间+90s)
判断shouldUseReadOnlyResponseCache为true(eureka-server.properties默认为true)
服务主动下线
正确的一分钟内期望的心跳次数计算公式为:服务实例个数 * (60 / 心跳时间间隔) * 0.85 = 每分钟最少的心跳次数
判断一分钟期望的心跳值 与 最近一分钟心跳数比较。最近一分钟心跳数是在心跳续约的时候累加的。
在心跳续约成功后,同步给其他服务端
主动下线
循环遍历需要摘除的实例,随机摘除
组装全量注册表的缓存key
InstanceInfoReplicator定时任务每隔40s注册到eureka-server。
使用AbstractJersey2EurekaHttpClient#cancel方法将当前InstanceInfo信息从eureka-server摘除。http://localhost:8080/v2/apps/serviceA/00000-1实际调用的是InstanceResource#cancelLease
180s定时过期
AbstractInstanceRegistry#register
从应用注册信息中获取到当前实例的心跳续约信息,获取不到就创建一个
注册的加上同步锁放入最近注册队列中recentRegisteredQueue
判断服务端是否进入了自我保护自制如果进入了自我保护机制,就不做服务实例摘除了,eureka-server默认时自己网络出现了问题
30s定时自动过期 只读缓存比较只读缓存与读写缓存中的数据,不相等就将读写缓存中的数据放入对应key的只读缓存中去
服务实例摘除
PeerAwareInstanceRegistryImpl#isLeaseExpirationEnabled()
多级缓存机制ResponseCache实现多级缓存机制
shutdown()
InstanceResource#cancelLease()
PeerAwareInstanceRegistryImpl#replicateToPeers注册表同步及高可用3层队列任务批处理
主动过期(新的服务实例发生注册、下线、故障)定时过期——读写缓存180s定时自动过期被动过期——只读缓存被动过期(默认30s)
在心跳续约的时候,最近一次心跳时间=心跳续约时间+90s这里进行故障校验的时候又将最近一次心跳时间+90s总共加了180s,如上次心跳的时间距离现在超过了180s,两分钟,才会任务服务实例故障;但是对于eureka设计来讲,他们是想在90s后就认为改服务实例已经过期;但是他们不修复此bug
注册(40s)
计算当前注册表在一分钟期望的心跳值(注册表服务实例数 * 2 * 0.85)
心跳失败
ApplicationsResource#getContainers()
PeerReplicationResource#batchReplication
注册的加上同步锁放入最近下线队列中recentCanceledQueue
从注册表中获取当前实例的心跳租约信息
将监听器(注册实例状态的变更)关闭。将注册任务、定时心跳续约任务、定时抓取增量注册表任务关闭。将实例管理器中的实例状态改为下线。将客户端网络通信组件关闭。
监听器(注册实例状态的变更)
19:55:00 3分钟 19:58:00 -> 过期EvictionTask本身调度的就慢了,比上一次该调度的时间晚了92s19:55:00过后,3分钟内没有心跳,在他延迟的这92s之内,也没心跳,19:59:32,都没心跳发送过,才能认为是失效
InstanceResource#renewLease()
服务下线、心跳、服务注册、服务状态变更...
获取全量注册表(key的name=ALL_APPS)
在初始化AcceptorExecuter的时候,会初始化一个AcceptorRunner线程,并且设置为后台线程,并且开始执行
AcceptorRunner
由BatchingDispatcher来将服务下线、心跳、服务注册、服务状态变更等交给AcceptorExecuter去处理
AcceptorQueue
batchWorkQueue
0 条评论
回复 删除
下一页