Eureka源码系列 —— 8.服务下线

前言

eureka源码系列已经过去了大半,这篇文章我们来看”服务下线“

正文

服务下线是指:服务实例主动下线,由服务实例所在的eureka-client主动发起,并且通知server进行注册表下线的功能。

client下线

client调用链路:

  • com.netflix.discovery.DiscoveryClient#shutdown
    • com.netflix.discovery.DiscoveryClient#cancelScheduledTasks
    • com.netflix.discovery.DiscoveryClient#unregister

image-20210626131813010

client端有一个shutdown方法,服务实例下线的时候,会主动调用这个方法。方法中会将client端启动的定时任务都停止,包括:心跳续约,定时拉取增量注册表等等。

image-20210626132132541

随后如果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

server端会调用com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#cancel方法处理请求:

image-20210626134505437

这个方法有三步:

  1. 调用父类AbstractInstanceRegistry#cancel方法,处理服务下线的逻辑

  2. 通知server集群内的其他节点

  3. 维护心跳总数的正确性,这里简单粗暴的将心跳数进行-2。

    笔者认为这样的处理不好,如果心跳间隔不是30s一次的话,就会引起bug

父类的cancel方法中,直接调用了com.netflix.eureka.registry.AbstractInstanceRegistry#internalCancel方法,这个方法在《服务踢除》中也被提到过,说明这是server处理服务下线的统一入口。

internalCancel

image-20210626135212195

方法逻辑不复杂,有四步:

  1. 从原始注册表数据结构中,删除下线的实例
  2. 对实例执行下线的逻辑,其实没什么逻辑,就是保存了一下下线的时间戳evictionTimestamp
  3. 放入最近变更队列中,以便client拉取增量注册表的时候可以感知到有服务实例下线了
  4. 清空读写缓存,避免client拉取缓存时拉取到已经下线的服务实例

服务下线不会主动通知其他客户端,而是等其他客户端来拉取增量注册表的时候,才会感知到

posted @ 2021-06-28 19:40  孔令翰  阅读(408)  评论(0编辑  收藏  举报