下方是Eureka Client从Eureka Server获取实例信息的总体流程图,后面会详细介绍每个步骤。
Eureka Client在刚启动的时候会从Eureka Server全量获取一次注册信息,同时初始化Eureka Client本地实例信息缓存定时更新任务,默认30s一次 registryFetchIntervalSeconds = 30。
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider) {
//略去部分无用代码.....
//此时正在创建Client实例对象,也就是说Client刚启动的时候,全量获取一次实例信息保存到本地
if (clientConfig.shouldFetchRegistry() && !fetchRegistry(false)) {
//重点方法fetchRegistry(boolean forceFullRegistryFetch)
//没有获取成功,即fetchRegistry方法返回false,那么从备份中获取注册信息
//获取实例信息异常,可以实现BackupRegistry接口,让eureka client获取一些其他的实例信息
fetchRegistryFromBackup();
}
//略去部分无用代码.....
// finally, init the schedule tasks
//初始化调度任务,刷新Client本地缓存、心跳、实例状态信息复制
initScheduledTasks();
//略去部分无用代码.....
}
重点看fetchRegistry(boolean forceFullRegistryFetch)这个方法,参数forceFullRegistryFetch表示是否全量获取实例信息,可以通过这个参数配置eureka.client.disable-delta,默认是false,即默认采取增量获取模式,后面会讲增量与全量的区别,以及为什么默认采取增量模式。
private boolean fetchRegistry(boolean forceFullRegistryFetch) {
try {
// If the delta is disabled or if it is the first time, get all applications
Applications applications = getApplications();
if (clientConfig.shouldDisableDelta()
|| (!Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress()))
|| forceFullRegistryFetch
|| (applications == null)
|| (applications.getRegisteredApplications().size() == 0)
|| (applications.getVersion() == -1)) //Client application does not have latest library supporting delta
{
//略去log.....
//全量获取,并保存到本地缓存
getAndStoreFullRegistry();
} else {
//增量获取,并更新本地缓存,如果增量获取失败,进行一次全量获取
getAndUpdateDelta(applications);
}
applications.setAppsHashCode(applications.getReconcileHashCode());
logTotalInstances();
} catch (Throwable e) {
logger.error(PREFIX + "{} - was unable to refresh its cache! status = {}", appPathIdentifier, e.getMessage(), e);
return false;
} finally {
if (tracer != null) {
tracer.stop();
}
}
// Notify about cache refresh before updating the instance remote status
onCacheRefreshed();
// Update remote status based on refreshed data held in the cache
updateInstanceRemoteStatus();
return true;
}
主要看一下增量获取方法的实现,getAndUpdateDelta(Applications applications),delta的意思是数学阿拉伯字符,代表着增量。
注意下面delta == null的条件判断,如果增量获取没有获取到实例信息返回的是new Applications(),而不是null,返回null说明发生了异常。只有增量获取发生了异常,才会再进行一次全量获取。
private void getAndUpdateDelta(Applications applications) throws Throwable {
long currentUpdateGeneration = fetchRegistryGeneration.get();
Applications delta = null;
//增量获取,getDelta的实现
EurekaHttpResponse<Applications> httpResponse = eurekaTransport.queryClient.getDelta(remoteRegionsRef.get());
if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
delta = httpResponse.getEntity();
}
//如果增量获取失败,进行一次全量获取
//注意这个地方,是获取失败了,如果没有获取到,那么返回的是个new Applications();
if (delta == null) {
logger.warn("The server does not allow the delta revision to be applied because it i