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.exponentialBackOffBound
和 client.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.exponentialBackOffBound
和 lease.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 向服务端注册实例,有以下两种方式:
异步执行
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);
}
}
同步触发
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))
}