Eureka 客户端源码分析:心跳续约

前面章节介绍了 DiscoveryClient 类的构造方法,同时也分析了 CacheRefreshThread 刷新任务线程源码。本章节将介绍心跳续约任务线程 HeartbeatThread。源码如下:

/**
* The heartbeat task that renews the lease in the given intervals.
*/
private class HeartbeatThread implements Runnable {

   public void run() {
       // 调用 renew() 方法进行续约
       if (renew()) {
           lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
       }
   }
}

renew() 方法源码如下:

/**
* Renew with the eureka service by making the appropriate REST call
*/
boolean renew() {
   EurekaHttpResponse<InstanceInfo> httpResponse;
   try {
       // 通过 HTTP REST 请求给注册中心发送心跳信息
       httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
       logger.debug(PREFIX + "{} - Heartbeat status: {}", appPathIdentifier, httpResponse.getStatusCode());
       if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
           REREGISTER_COUNTER.increment();
           logger.info(PREFIX + "{} - Re-registering apps/{}", appPathIdentifier, instanceInfo.getAppName());
           long timestamp = instanceInfo.setIsDirtyWithTime();
           boolean success = register();
           if (success) {
               instanceInfo.unsetIsDirty(timestamp);
           }
           return success;
       }
       return httpResponse.getStatusCode() == Status.OK.getStatusCode();
   } catch (Throwable e) {
       logger.error(PREFIX + "{} - was unable to send heartbeat!", appPathIdentifier, e);
       return false;
   }
}

到这里续约源码分析完了。

接下来我们还需要看看 initScheduledTasks() 方法最后的  instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds()) 语句,该语句将当前服务注册到注册中心。instanceInfoReplicator.start() 方法的源码如下:

public void start(int initialDelayMs) {
   if (started.compareAndSet(false, true)) {
       instanceInfo.setIsDirty();  // for initial register
       // 启动一个定时任务,任务指向this,将执行 InstanceInfoReplicator 类下面的 run() 方法
       Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
       scheduledPeriodicRef.set(next);
   }
}

上面中 scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS) 将当前类 this 作为执行任务,这是因为该类实现了 Runnable,代码如下:

class InstanceInfoReplicator implements Runnable {
   //...
}

InstanceInfoReplicator 中的 run() 方法源码如下:

public void run() {
   try {
       discoveryClient.refreshInstanceInfo();

       Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
       if (dirtyTimestamp != null) {
           // 调用 register() 方法实现服务注册
           discoveryClient.register();
           instanceInfo.unsetIsDirty(dirtyTimestamp);
       }
   } catch (Throwable t) {
       logger.warn("There was a problem with the instance info replicator", t);
   } finally {
       Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
       scheduledPeriodicRef.set(next);
   }
}

到这里 DiscoveryClient 类基本分析完成了,后续章节将介绍 Eureka 服务源码。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号