Eureka 源码分析(四)

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

前面章节介绍了 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 服务源码。

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