深入理解SpringCloud源码探究篇 | Eureka客户端源码分析

  • Post author:
  • Post category:其他


SpringCloud系列:


  1. SpringCloud入门必看例子

  2. 深入理解SpringCloud源码探究篇 | Eureka服务端源码分析

  3. 深入理解SpringCloud源码探究篇 | Eureka客户端源码分析

  4. 深入理解SpringCloud源码探究篇 | ribbon源码分析

  5. 深入理解SpringCloud源码探究篇 | Feign源码分析

虽然说官方已经发布Eureka不在维护的通知,但是还是需要对我们用过的Eureka进行深入了解的,因为这些玩意都是大同小异的。

下面先利用白话文分析Eureka客户端的实现原理:

eureka客户端:

调用eureka服务端接口进行服务列表获取:

eureka客户端启动后初始化

EurekaClientAutoConfiguration

自动配置加载bean

CloudEurekaClient

(这里会通过jersey进行调用eureka服务端接口(ApplicationsResource.getContainers)请求拿到所有注册的客户端服务):

DiscoveryClient

【CloudEurekaClient的父类】初始化的时候会调用initScheduledTasks启动一个延迟任务默认30秒后执行的一个

TimedSupervisorTask

单任务(该任务里面又启动一个每延迟30秒【同前面的30秒】重新复调用TimedSupervisorTask)其实就是形成一个定时任务启动后30秒执行之后每间隔30秒执行任务,实际调用进程DiscoveryClient.CacheRefreshThread的refreshRegistry方法进行服务的新增(DiscoveryClient.fetchRegistry>DiscoveryClient.getAndStoreFullRegistry)或是更新(getAndUpdateDelta(applications)),总之就是进行服务的拉取(调用

AbstractJerseyEurekaHttpClient

.getApplications进行jersey请求eureka服务端接口(ApplicationsResource.getContainers;)拿到服务列表)然后放入服务列表缓存DiscoveryClient.

localRegionApps



调用eureka服务端接口进行服务注册:

eureka客户端启动后初始化 EurekaClientAutoConfiguration 自动配置加载bean CloudEurekaClient (这里会通过jersey进行调用eureka服务端接口(ApplicationResource.addInstance)请求注册服务):DiscoveryClient【CloudEurekaClient的父类】初始化的时候会调用DiscoveryClient.register()方法这里将进行发起jersey请求调用服务端接口进行InstanceInfo信息注册。

客户端定时向服务端发送心跳请求进行续约时间刷新,这里与上面的服务列表更新一样也是构造一个TimedSupervisorTask定时任务,实际调用进程是HeartbeatThread,该进程调用DiscoveryClient.renew()发起jersey请求服务端的接口(InstanceResource.renewLease())进行服务的续约然后也刷新DiscoveryClient.lastSuccessfulHeartbeatTimestamp时间。当自己下线时触发主动发送剔除服务请求,其实利用@PreDestroy就是当bean注销时进行该方法操作,调用DiscoveryClient.shutdown让所有定时任务停止以及发起jersey请求调用服务端InstanceResource.cancelLease()接口进行主动请求剔除

eureka客户端核心大致的实现如上面所说, 下面进行源码的探究:


EurekaClientAutoConfiguration 自动配置类

注册了CloudEurekaClient的bean,先看下该类的继承结构:

前面白话文中描述到在初始化CloudEurekaClient过程中会进行开启一个定时任务然后进行服务的获取以及服务更新操作以及服务的注册操作,下面看下究竟


服务列表获取

在构造父类DiscoveryClient时会进行调用initScheduledTasks:

这里启动了一个单次延时任务TimedSupervisorTask,TimedSupervisorTask继承TimerTask实现run方法具体我看下:

从上面我们可以看到提交任务后再finally又重新启动一个单次延时任务,其实就是起到一个延迟的定时任务作用。

接着我们看看其实际的操作线程CacheRefreshThread:

直接调用refreshRegistry()方法,该方法其他细节都不用看了:

boolean success = fetchRegistry(remoteRegionsModified);

接着进入fetchRegistry:

该方法就是开始进行服务列表的获取,先是获取当前缓存是否有服务列表,如果有进行更新操作,如果没有进行新增获取操作,我们就看看这个getAndStoreFullRegistry获取所有服务列表的新增操作吧 :

以上方法中我们可以看到通过调用getApplications,用的是AbstractJerseyEurekaHttpClient:

接着调用getApplicationsInternal:

以上可以清楚的看到利用jerseyClient进行请求eureka服务端接口的调用,获取到服务列表然后进行返回,然后放入DiscoveryClient的localRegionApps里这样就完成了服务的获取操作。


服务注册

同样在注册构造父类DiscoveryClient时会进行调用注册操作:

这里判断服务是否已经注册,我们看下register这个方法:

调用的是AbstractJerseyEurekaHttpClient的register:

圈红的我们可以看出这里就是利用jerseyClient向eureka服务端发起服务注册请求,这样就完成了服务的注册操作。


服务续约

同样在注册构造父类DiscoveryClient时会进行启动一个定时任务进行续约,也就是所谓的定时向服务端发送心跳:

前面获取服务列表的时候我们提到的调用initScheduledTasks进行启动定时任务获取服务,这下面还有一个定时任务就是启动续约的定时任务:

其他的不在赘述,直接查看操作的心跳进程HeartbeatThread:

调用renew方法,续约完成后刷新lastSuccessfulHeartbeatTimestamp为当前时间,来看看这个renew方法:

接着调用AbstractJerseyEurekaHttpClient的sendHeartBeat方法:

这里我们可以看到利用jerseyClient向eureka服务端发送心跳请求,这样服务就完成了续约操作。


服务下线剔除

同样在DiscoveryClient里有如下方法,当bean被注销时会调用shutdown方法进行服务下线操作


cancelScheduledTasks停止所以定时任务,unregister发起服务注销操作:

调用AbstractJerseyEurekaHttpClient.cancel:

如上利用jerseyClient向eureka服务端发送服务下线请求,这样就完成了服务的下线剔除操作。


总结

eureka客户端服务启动时初始化 DiscoveryClient调用register进行向eureka服务端发送注册操作;接着进行调用initScheduledTasks启动各种定时任务,包括:服务列表定时向eureka服务端发送获取服务列表接着放入localRegionApps缓存,以及启动一个心跳任务,定时向eureka服务端发送心跳进行续约操作;当客户端DiscoveryClient注销时进行调用unregister向服务端发送下线剔除。



版权声明:本文为u011320740原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。