Eureka 学习笔记2:客户端 DiscoveryClient

DiscoveryClient # cacheRefreshTask

// 配置shouldFetchRegistry
if (clientConfig.shouldFetchRegistry()) {
    // 配置client.refresh.interval
    int registryFetchIntervalSeconds = clientConfig
        .getRegistryFetchIntervalSeconds();
    // 配置expBackOffBound
    int expBackOffBound = clientConfig
        .getCacheRefreshExecutorExponentialBackOffBound();

    cacheRefreshTask = new TimedSupervisorTask(
        "cacheRefresh",
        scheduler,
        cacheRefreshExecutor,
        registryFetchIntervalSeconds,
        TimeUnit.SECONDS,
        expBackOffBound,
        new CacheRefreshThread()
    );

    scheduler.schedule(
        cacheRefreshTask,
        registryFetchIntervalSeconds, TimeUnit.SECONDS);
}

shouldFetchRegistry 指定是否从服务端拉取注册列表,默认true

client.refresh.interval 指定从服务端拉取注册列表的时间间隔,默认30s

client.cacheRefresh.exponentialBackOffBound 指定从服务端拉取注册列表的最大时间间隔,默认10

注1:当从服务端拉取注册列表的请求超时(即 TimedSupervisorTask 捕获 TimeoutException 异常时),下一次拉取的时间间隔会成倍递增,递增后的时间间隔不能超过 client.cacheRefresh.exponentialBackOffBoundclient.refresh.interval 的乘积(即拉取的时间间隔最大不能超过 10x30=300s)

注2
supervisor

/ˈsuːpəvaɪzə®/

/ˈsuːpərvaɪzər/
n.
监督人;主管人;指导者

注3
exponential

/ˌekspəˈnenʃl/

/ˌekspəˈnenʃl/
adj.
指数的;幂的;越来越快的;由指数表示的
n.
指数


DiscoveryClient # heartbeatTask

if (clientConfig.shouldRegisterWithEureka()) {
    int renewalIntervalInSecs = instanceInfo
        .getLeaseInfo().getRenewalIntervalInSecs();
    int expBackOffBound = clientConfig
        .getHeartbeatExecutorExponentialBackOffBound();

    heartbeatTask = new TimedSupervisorTask(
        "heartbeat",
        scheduler,
        heartbeatExecutor,
        renewalIntervalInSecs,
        TimeUnit.SECONDS,
        expBackOffBound,
        new HeartbeatThread()
    );

    scheduler.schedule(
        heartbeatTask,
        renewalIntervalInSecs, TimeUnit.SECONDS);
}

registration.enabled 指定是否向服务端注册实例,默认true

lease.renewalInterval 指定向服务端续约的时间间隔,默认30s

lease.duration 指定向服务端续约的租期时间,默认90s

client.heartbeat.exponentialBackOffBound 指定向服务端续约的最大时间间隔,默认10

注1:当向服务端续约的请求超时(即 TimedSupervisorTask 捕获 TimeoutException 异常时),下一次进行续约的时间间隔会成倍递增,递增后的时间间隔不能超过 client.heartbeat.exponentialBackOffBoundlease.renewalInterval 的乘积(即进行续约的时间间隔最大不能超过 10x30=300s)


DiscoveryClient # instanceInfoReplicator

// 配置registration.enabled
if (clientConfig.shouldRegisterWithEureka()) {
    // ...
    instanceInfoReplicator = new InstanceInfoReplicator(
        this,
        instanceInfo,
        // 配置appinfo.replicate.interval
        clientConfig.getInstanceInfoReplicationIntervalSeconds(),
        // burstSize
        2);

    statusChangeListener = new ApplicationInfoManager.StatusChangeListener()
        {
            @Override
            public void notify(StatusChangeEvent statusChangeEvent) {
                instanceInfoReplicator.onDemandUpdate();
            }
        };

    // 配置shouldOnDemandUpdateStatusChange
    if (clientConfig.shouldOnDemandUpdateStatusChange()) {
        applicationInfoManager
            .registerStatusChangeListener(statusChangeListener);
    }

    instanceInfoReplicator.start(
        // 配置appinfo.initial.replicate.time
        clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
}

registration.enabled 指定是否向服务端注册实例,默认true

appinfo.replicate.interval 指定向服务端注册实例的时间间隔,默认30s

appinfo.initial.replicate.time 指定初次向服务端注册实例的延迟时间,默认40s

shouldOnDemandUpdateStatusChange 指定是否启用 StatusChangeListener,在实例状态更新时向服务端注册实例,默认true


客户端通过 InstanceInfoReplicator 向服务端注册实例,有以下两种方式:

  1. scheduler 周期地异步执行 InstanceInfoReplicator 的 run 方法
public void run() {
    try {
        // 刷新实例信息
        discoveryClient.refreshInstanceInfo();
        Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
        // 如果实例信息发生了更新
        if (dirtyTimestamp != null) {
            // 向服务端注册实例
            discoveryClient.register();
            // 重置实例的dirty状态
            instanceInfo.unsetIsDirty(dirtyTimestamp);
        }
    } catch (Throwable t) {
    } finally {
        // scheduler进行下一次延迟调度
        Future next = scheduler
            .schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
        scheduledPeriodicRef.set(next);
    }
}
  1. 实例状态发生变化时,statusChangeListener 同步触发 InstanceInfoReplicator 的 onDemandUpdate 方法,scheduler 异步执行 InstanceInfoReplicator 的 run 方法
public boolean onDemandUpdate() {
    // 令牌桶限流,如果rateLimiter成功获取令牌
    if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {
        // 如果scheduler没有关闭
        if (!scheduler.isShutdown()) {
            scheduler.submit(new Runnable() {
                @Override
                public void run() {
                    Future latestPeriodic = scheduledPeriodicRef.get();
                    // 如果scheduler正在执行则取消
                    if (latestPeriodic != null && !latestPeriodic.isDone()) {
                        latestPeriodic.cancel(false);
                    }
                    InstanceInfoReplicator.this.run();
                }
            });
            return true;
        } // end if (!scheduler.isShutdown())
    } // end if (rateLimiter.acquire(burstSize, allowedRatePerMinute))
}

你可能感兴趣的:(eureka,eureka)