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 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号