Eureka源码系列 —— 8.服务下线
前言
eureka源码系列已经过去了大半,这篇文章我们来看”服务下线“。
正文
服务下线是指:服务实例主动下线,由服务实例所在的eureka-client主动发起,并且通知server进行注册表下线的功能。
client下线
client调用链路:
- com.netflix.discovery.DiscoveryClient#shutdown
- com.netflix.discovery.DiscoveryClient#cancelScheduledTasks
- com.netflix.discovery.DiscoveryClient#unregister
client端有一个shutdown
方法,服务实例下线的时候,会主动调用这个方法。方法中会将client端启动的定时任务都停止,包括:心跳续约,定时拉取增量注册表等等。
随后如果client注册到了server的话,通知server端进行实例下线。com.netflix.discovery.DiscoveryClient#unregister
方法里就是对server发起了一个远程调用。我们直接去看server的处理逻辑
server处理服务下线
server调用链路:
- com.netflix.eureka.resources.InstanceResource#cancelLease
- com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#cancel
- com.netflix.eureka.registry.AbstractInstanceRegistry#cancel
- com.netflix.eureka.registry.AbstractInstanceRegistry#internalCancel
- com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#replicateToPeers
- com.netflix.eureka.registry.AbstractInstanceRegistry#cancel
- com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#cancel
server端会调用com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#cancel
方法处理请求:
这个方法有三步:
-
调用父类
AbstractInstanceRegistry#cancel
方法,处理服务下线的逻辑 -
通知server集群内的其他节点
-
维护心跳总数的正确性,这里简单粗暴的将心跳数进行-2。
笔者认为这样的处理不好,如果心跳间隔不是30s一次的话,就会引起bug
父类的cancel方法中,直接调用了com.netflix.eureka.registry.AbstractInstanceRegistry#internalCancel
方法,这个方法在《服务踢除》中也被提到过,说明这是server处理服务下线的统一入口。
internalCancel
方法逻辑不复杂,有四步:
- 从原始注册表数据结构中,删除下线的实例
- 对实例执行下线的逻辑,其实没什么逻辑,就是保存了一下下线的时间戳evictionTimestamp
- 放入最近变更队列中,以便client拉取增量注册表的时候可以感知到有服务实例下线了
- 清空读写缓存,避免client拉取缓存时拉取到已经下线的服务实例
服务下线不会主动通知其他客户端,而是等其他客户端来拉取增量注册表的时候,才会感知到