08、Eureka源码系列-服务下线

前言

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

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

 

这个方法有三步:

  1. 调用父类AbstractInstanceRegistry#cancel方法,处理服务下线的逻辑
    2、 通知server集群内的其他节点;
    3、 维护心跳总数的正确性,这里简单粗暴的将心跳数进行-2;

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

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

internalCancel

 

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

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

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