spring-cloud-netflix-eureka-client/2.2.9.RELEASE/spring-cloud-netflix-eureka-client-2.2.9.RELEASE-sources.jar!/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration,\
//看到这里
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration
EurekaClientAutoConfiguration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter(name = {
"org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration",
"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
public class EurekaClientAutoConfiguration {
//省略其他源码
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingRefreshScope
protected static class EurekaClientConfiguration {
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class,
search = SearchStrategy.CURRENT)
public EurekaClient eurekaClient(ApplicationInfoManager manager,
EurekaClientConfig config) {
//创建了CloudEurekaClient
return new CloudEurekaClient(manager, config, this.optionalArgs,
this.context);
}
}
}
CloudEurekaClient的父类DiscoveryClient的构造函数
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
//省略部分代码
initScheduledTasks();
}
private void initScheduledTasks() {
//fetchRegistry默认为true
if (clientConfig.shouldFetchRegistry()) {
//registryFetchIntervalSeconds 默认30秒 ,从eureka服务端拉取服务列表
int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
cacheRefreshTask = new TimedSupervisorTask(
"cacheRefresh",
scheduler,
cacheRefreshExecutor,
registryFetchIntervalSeconds,
TimeUnit.SECONDS,
expBackOffBound,
new CacheRefreshThread()
);
scheduler.schedule(
cacheRefreshTask,
registryFetchIntervalSeconds, TimeUnit.SECONDS);
}
//registerWithEureka默认为true
if (clientConfig.shouldRegisterWithEureka()) {
//renewalIntervalInSecs默认为30s,心跳续约间隔
int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs);
// Heartbeat timer
heartbeatTask = new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new HeartbeatThread()
);
scheduler.schedule(
heartbeatTask,
renewalIntervalInSecs, TimeUnit.SECONDS);
// InstanceInfo replicator
instanceInfoReplicator = new InstanceInfoReplicator(
this,
instanceInfo,
clientConfig.getInstanceInfoReplicationIntervalSeconds(),
2); // burstSize
//创建状态改变监听器,监听实例状态改变,立即向服务端汇报
statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
@Override
public String getId() {
return "statusChangeListener";
}
@Override
public void notify(StatusChangeEvent statusChangeEvent) {
logger.info("Saw local status change event {}", statusChangeEvent);
instanceInfoReplicator.onDemandUpdate();
}
};
if (clientConfig.shouldOnDemandUpdateStatusChange()) {
//注册状态改变监听器,就是放到listeners中
applicationInfoManager.registerStatusChangeListener(statusChangeListener);
}
//定时把实例状态状态向服务端汇报
//将isInstanceInfoDirty修改为true
instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
} else {
logger.info("Not registering with Eureka server per configuration");
}
}
class CacheRefreshThread implements Runnable {
public void run() {
//从注册中心拉取服务列表
refreshRegistry();
}
}
@VisibleForTesting
void refreshRegistry() {
try {
//省略部分代码
boolean success = fetchRegistry(remoteRegionsModified);
if (success) {
//更新服务列表的个数
registrySize = localRegionApps.get().size();
//更新最近一次拉取服务列表的时间
lastSuccessfulRegistryFetchTimestamp = System.currentTimeMillis();
}
//省略部分代码
} catch (Throwable e) {
logger.error("Cannot fetch registry from server", e);
}
}
private boolean fetchRegistry(boolean forceFullRegistryFetch) {
Stopwatch tracer = FETCH_REGISTRY_TIMER.start();
try {
//从localRegionApps(客户端本地缓存的服务列表信息) 获取 服务应用
Applications applications = getApplications();
//是否禁用增量拉取,默认false
if (clientConfig.shouldDisableDelta()
//eureka服务端地址不为空
|| (!Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress()))
//入参forceFullRegistryFetch可以传入true,强制进行全量拉取
|| forceFullRegistryFetch
//本地服务列表为空
|| (applications == null)
|| (applications.getRegisteredApplications().size() == 0)
|| (applications.getVersion() == -1)) //Client application does not have latest library supporting delta
{
logger.info("Disable delta property : {}", clientConfig.shouldDisableDelta());
logger.info("Single vip registry refresh property : {}", clientConfig.getRegistryRefreshSingleVipAddress());
logger.info("Force full registry fetch : {}", forceFullRegistryFetch);
logger.info("Application is null : {}", (applications == null));
logger.info("Registered Applications size is zero : {}",
(applications.getRegisteredApplications().size() == 0));
logger.info("Application version is -1: {}", (applications.getVersion() == -1));
//全量拉取
getAndStoreFullRegistry();
}
//增量拉取
else {
getAndUpdateDelta(applications);
}
//设置服务列表计算出的hashcode
applications.setAppsHashCode(applications.getReconcileHashCode());
logTotalInstances();
} catch (Throwable e) {
logger.info(PREFIX + "{} - was unable to refresh its cache! This periodic background refresh will be retried in {} seconds. status = {} stacktrace = {}",
appPathIdentifier, clientConfig.getRegistryFetchIntervalSeconds(), e.getMessage(), ExceptionUtils.getStackTrace(e));
return false;
} finally {
if (tracer != null) {
tracer.stop();
}
}
//发布CacheRefreshedEvent事件 和 HeartbeatEvent事件(子类CloudEurekaClient发布)
onCacheRefreshed();
//发布StatusChangeEvent事件
updateInstanceRemoteStatus();
// registry was fetched successfully, so return true
return true;
}
private void getAndStoreFullRegistry() throws Throwable {
//获取上一次拉去服务列表的generation
long currentUpdateGeneration = fetchRegistryGeneration.get();
logger.info("Getting all instance registry info from the eureka server");
Applications apps = null;
EurekaHttpResponse<Applications> httpResponse = clientConfig.getRegistryRefreshSingleVipAddress() == null
//远程调用,从eureka服务端拉去服务列表。
//这里的eurekaTransport.queryClient被多个不同功能的类包装,着重来看RetryableEurekaHttpClient
? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get())
: eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());
if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
apps = httpResponse.getEntity();
}
logger.info("The response status is {}", httpResponse.getStatusCode());
if (apps == null) {
logger.error("The application is null for some reason. Not storing this information");
}
//cas更新currentUpdateGeneration + 1
else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {
//全量更新本地服务列表缓存
localRegionApps.set(this.filterAndShuffle(apps));
logger.debug("Got full registry with apps hashcode {}", apps.getAppsHashCode());
} else {
logger.warn("Not updating applications as another thread is updating it already");
}
}
private void getAndUpdateDelta(Applications applications) throws Throwable {
//获取上一次拉去服务列表的generation
long currentUpdateGeneration = fetchRegistryGeneration.get();
Applications delta = null;
//从eureka服务端增量获取服务列表。
EurekaHttpResponse<Applications> httpResponse = eurekaTransport.queryClient.getDelta(remoteRegionsRef.get());
if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
delta = httpResponse.getEntity();
}
if (delta == null) {
logger.warn("The server does not allow the delta revision to be applied because it is not safe. "
+ "Hence got the full registry.");
//增量拉取未获取到数据,重新全量拉取
getAndStoreFullRegistry();
}
//cas更新currentUpdateGeneration + 1
else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {
logger.debug("Got delta update with apps hashcode {}", delta.getAppsHashCode());
String reconcileHashCode = "";
//加锁
if (fetchRegistryUpdateLock.tryLock()) {
try {
//增量更新本地服务列表缓存
updateDelta(delta);
//计算更新后的所有服务列表的hashCode
reconcileHashCode = getReconcileHashCode(applications);
} finally {
fetchRegistryUpdateLock.unlock();
}
} else {
logger.warn("Cannot acquire update lock, aborting getAndUpdateDelta");
}
// There is a diff in number of instances for some reason
//判断更新后的hashCode , 和eureka服务端回传的的hashCode 是否一致
if (!reconcileHashCode.equals(delta.getAppsHashCode()) || clientConfig.shouldLogDeltaDiff()) {
//不一致, 则 重新全量拉取服务列表更新本地缓存
reconcileAndLogDifference(delta, reconcileHashCode); // this makes a remoteCall
}
}
else {
logger.warn("Not updating application delta as another thread is updating it already");
logger.debug("Ignoring delta update with apps hashcode {}, as another thread is updating it already", delta.getAppsHashCode());
}
}
private void updateDelta(Applications delta) {
int deltaCount = 0;
//循环所有的增量拉取的服务列表
for (Application app : delta.getRegisteredApplications()) {
//循环服务下的所有实例
for (InstanceInfo instance : app.getInstances()) {
//从 localRegionApps本地缓存 获取到所有服务applications
Applications applications = getApplications();
String instanceRegion = instanceRegionChecker.getInstanceRegion(instance);
if (!instanceRegionChecker.isLocalRegion(instanceRegion)) {
Applications remoteApps = remoteRegionVsApps.get(instanceRegion);
if (null == remoteApps) {
remoteApps = new Applications();
remoteRegionVsApps.put(instanceRegion, remoteApps);
}
applications = remoteApps;
}
++deltaCount;
//如果是新增的服务实例
if (ActionType.ADDED.equals(instance.getActionType())) {
//从 applications 使用服务名称获取到服务
Application existingApp = applications.getRegisteredApplications(instance.getAppName());
if (existingApp == null) {
//获取不到,则添加
applications.addApplication(app);
}
logger.debug("Added instance {} to the existing apps in region {}", instance.getId(), instanceRegion);
//将服务实例添加到服务列表中
applications.getRegisteredApplications(instance.getAppName()).addInstance(instance);
}
//修改的服务实例
else if (ActionType.MODIFIED.equals(instance.getActionType())) {
//和新增一样的操作
Application existingApp = applications.getRegisteredApplications(instance.getAppName());
if (existingApp == null) {
applications.addApplication(app);
}
logger.debug("Modified instance {} to the existing apps ", instance.getId());
applications.getRegisteredApplications(instance.getAppName()).addInstance(instance);
}
//删除的服务实例
else if (ActionType.DELETED.equals(instance.getActionType())) {
//从 applications 使用服务名称获取到服务
Application existingApp = applications.getRegisteredApplications(instance.getAppName());
if (existingApp != null) {
logger.debug("Deleted instance {} to the existing apps ", instance.getId());
//从该服务中移除该服务实例
existingApp.removeInstance(instance);
/*
* We find all instance list from application(The status of instance status is not only the status is UP but also other status)
* if instance list is empty, we remove the application.
*/
//获取对应的服务的所有服务实例,如果为空,则移除该服务
if (existingApp.getInstancesAsIsFromEureka().isEmpty()) {
applications.removeApplication(existingApp);
}
}
}
}
}
logger.debug("The total number of instances fetched by the delta processor : {}", deltaCount);
getApplications().setVersion(delta.getVersion());
getApplications().shuffleInstances(clientConfig.shouldFilterOnlyUpInstances());
for (Applications applications : remoteRegionVsApps.values()) {
applications.setVersion(delta.getVersion());
applications.shuffleInstances(clientConfig.shouldFilterOnlyUpInstances());
}
}
private class HeartbeatThread implements Runnable {
public void run() {
//心跳续约
if (renew()) {
//更新最后最后一次心跳续约的时间
lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
}
}
}
boolean renew() {
EurekaHttpResponse<InstanceInfo> httpResponse;
try {
//远程调用,发送心跳续约请求
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;
}
}
boolean register() throws Throwable {
logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
EurekaHttpResponse<Void> httpResponse;
try {
//发送服务实例注册请求
//registrationClient一样被RetryableEurekaHttpClient所包装
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
throw e;
}
if (logger.isInfoEnabled()) {
logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
}
return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}
RetryableEurekaHttpClient
@Override
protected <R> EurekaHttpResponse<R> execute(RequestExecutor<R> requestExecutor) {
List<EurekaEndpoint> candidateHosts = null;
int endpointIdx = 0;
//写死了 numberOfRetries 为 3次
for (int retry = 0; retry < numberOfRetries; retry++) {
//持有了currentHttpClient
EurekaHttpClient currentHttpClient = delegate.get();
EurekaEndpoint currentEndpoint = null;
//如果currentHttpClient 为空
if (currentHttpClient == null) {
if (candidateHosts == null) {
//获取配置的所有eureka服务端实例
candidateHosts = getHostCandidates();
if (candidateHosts.isEmpty()) {
throw new TransportException("There is no known eureka server; cluster server list is empty");
}
}
if (endpointIdx >= candidateHosts.size()) {
throw new TransportException("Cannot execute request on any known server");
}
//endpointIdx加一,每次循环重试 获取到不同的eureka服务端
currentEndpoint = candidateHosts.get(endpointIdx++);
//设置为currentHttpClient
currentHttpClient = clientFactory.newClient(currentEndpoint);
}
try {
//currentHttpClient交给下一个包装类去完成调用
EurekaHttpResponse<R> response = requestExecutor.execute(currentHttpClient);
//eureka服务端相应的状态码 为 客户端可以接受的状态码 ,则说明调用正常返回。直接返回响应结果
if (serverStatusEvaluator.accept(response.getStatusCode(), requestExecutor.getRequestType())) {
delegate.set(currentHttpClient);
if (retry > 0) {
logger.info("Request execution succeeded on retry #{}", retry);
}
return response;
}
//不是服务端正常返回的状态码 。 需要重试,进行下次循环
logger.warn("Request execution failure with status code {}; retrying on another server if available", response.getStatusCode());
} catch (Exception e) {
//发生异常,需要重试
logger.warn("Request execution failed with message: {}", e.getMessage()); // just log message as the underlying client should log the stacktrace
}
// Connection error or 5xx from the server that must be retried on another server
//将currentHttpClient设置为空。切换到其他eureka节点去调用
delegate.compareAndSet(currentHttpClient, null);
if (currentEndpoint != null) {
quarantineSet.add(currentEndpoint);
}
}
throw new TransportException("Retry limit reached; giving up on completing the request");
}
void refreshInstanceInfo() {
applicationInfoManager.refreshDataCenterInfoIfRequired();
//刷新本地lease信息
applicationInfoManager.refreshLeaseInfoIfRequired();
InstanceStatus status;
try {
//获取健康检查实现类
//可以实现HealthCheckHandler接口,作为bean注入到容器中。没有的话,默认实例化一个HealthCheckCallbackToHandlerBridge(过时了,支持HealthCheckCallback接口)
//EurekaClient会依赖注入HealthCheckHandler类型的bean。
status = getHealthCheckHandler().getStatus(instanceInfo.getStatus());
} catch (Exception e) {
logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
status = InstanceStatus.DOWN;
}
//通知状态改变监听器
if (null != status) {
applicationInfoManager.setInstanceStatus(status);
}
}
InstanceInfoReplicator
class InstanceInfoReplicator implements Runnable {
public void start(int initialDelayMs) {
if (started.compareAndSet(false, true)) {
//修改isInstanceInfoDirty为true , 初始发送客户端注册请求
instanceInfo.setIsDirty(); // for initial register
//延迟initialDelayMs,执行一次
Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
//设置Future 到 scheduledPeriodicRef
scheduledPeriodicRef.set(next);
}
}
public void run() {
try {
//刷新本地lease信息
discoveryClient.refreshInstanceInfo();
//如果isInstanceInfoDirty为true , 返回lastDirtyTimestamp
//否则,返回null
Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
//发送实例注册请求 。
//如果 服务端 的 客户端实例 不存在,则完成实例注册
//如果 服务端 的 客户端实例 存在, 则更新实例的状态
discoveryClient.register();
//设置isInstanceInfoDirty为false
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);
//Future 设置到 scheduledPeriodicRef中
scheduledPeriodicRef.set(next);
}
}
public boolean onDemandUpdate() {
if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {
if (!scheduler.isShutdown()) {
//立即执行
scheduler.submit(new Runnable() {
@Override
public void run() {
logger.debug("Executing on-demand update of local InstanceInfo");
//获取下一次准备执行的任务的future
Future latestPeriodic = scheduledPeriodicRef.get();
//如果还没有执行,则取消该任务
if (latestPeriodic != null && !latestPeriodic.isDone()) {
logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");
latestPeriodic.cancel(false);
}
//调用run方法,发送注册请求以更新客户端状态
InstanceInfoReplicator.this.run();
}
});
return true;
} else {
logger.warn("Ignoring onDemand update due to stopped scheduler");
return false;
}
} else {
logger.warn("Ignoring onDemand update due to rate limiter");
return false;
}
}
}
ApplicationInfoManager
public void refreshLeaseInfoIfRequired() {
//获取lease
LeaseInfo leaseInfo = instanceInfo.getLeaseInfo();
if (leaseInfo == null) {
return;
}
//实例过期时间间隔
int currentLeaseDuration = config.getLeaseExpirationDurationInSeconds();
//心跳续约间隔
int currentLeaseRenewal = config.getLeaseRenewalIntervalInSeconds();
//判断lease的 过期时间间隔 心跳续约间隔 是否和 配置的一致, 不一致,则创建新的lease ,设置到instanceInfo中
if (leaseInfo.getDurationInSecs() != currentLeaseDuration || leaseInfo.getRenewalIntervalInSecs() != currentLeaseRenewal) {
LeaseInfo newLeaseInfo = LeaseInfo.Builder.newBuilder()
.setRenewalIntervalInSecs(currentLeaseRenewal)
.setDurationInSecs(currentLeaseDuration)
.build();
instanceInfo.setLeaseInfo(newLeaseInfo);
instanceInfo.setIsDirty();
}
}
public synchronized void setInstanceStatus(InstanceStatus status) {
//更新后的状态
InstanceStatus next = instanceStatusMapper.map(status);
if (next == null) {
return;
}
//更新前的状态
InstanceStatus prev = instanceInfo.setStatus(next);
if (prev != null) {
//遍历listeners,调用notify方法
for (listener : listeners.values()) {
try {
listener.notify(new StatusChangeEvent(prev, next));
} catch (Exception e) {
logger.warn("failed to notify listener: {}", listener.getId(), e);
}
}
}
}