spring cloud eureka源码分析(三)

        通过前面文章的分析EurekaClientAutoConfiguration类中EurekaClientConfigBean和EurekaInstanceConfigBean的配置属性说明,我们在看看EurekaServiceRegistry这个类bean的注入,进入该类我们看到它实现了ServiceRegistry接口

 这个接口是我们spring cloud提供的用于服务注册的接口,在接口上面它同时提供了EurekaRegistration实例对象的依赖,进入到EurekaRegistration类可以了解到该类实现了Registration接口


      通过代码我们发现它实现了接口中返回值的信息初始化,同时在其内部类Builder中在对象没有初始化的时候初始化对象赋值,并返回EurekaRegistration对象。

public EurekaRegistration build() {
	Assert.notNull(instanceConfig, "instanceConfig may not be null");

	if (this.applicationInfoManager == null) {
		InstanceInfo instanceInfo = new InstanceInfoFactory()
				.create(this.instanceConfig);
		this.applicationInfoManager = new ApplicationInfoManager(
				this.instanceConfig, instanceInfo);
	}
	if (this.eurekaClient == null) {
		Assert.notNull(this.clientConfig,
				"if eurekaClient is null, EurekaClientConfig may not be null");
		Assert.notNull(this.publisher,
				"if eurekaClient is null, ApplicationEventPublisher may not be null");

		this.eurekaClient = new CloudEurekaClient(this.applicationInfoManager,
				this.clientConfig, this.publisher);
	}
	return new EurekaRegistration(instanceConfig, eurekaClient,
			applicationInfoManager, healthCheckHandler);
}

     我们在回到EurekaServiceRegistry类中,可以看到它有以下方法

 它实现了服务注册,取消注册,状态设置等方法,我们先分析下register()方法:

  通过私有方法maybeInitializeClient()获取当前注册的实例对象以及服务器上面返回的所有注册信息

private void maybeInitializeClient(EurekaRegistration reg) {
  // force initialization of possibly scoped proxies
  reg.getApplicationInfoManager().getInfo();
  reg.getEurekaClient().getApplications();
}

 最后在register()方法里面设置状态为UP及健康检查的连接地址。在deregister()方法中则只是将状态值设置为DOWN作为注销标志。

     接下来我们了解下ApplicationInfoManager bean的注入,它通过我们前面已经注入过的EurekaClientConfigBean获取client配置信息,通过InstanceInfoFactory类的create()方法将配置信息复制到Netflix的InstanceInfo对象中,然后将InstanceInfo对象传递给ApplicationInfoManager,进入到ApplicationInfoManager类,看看它的结果如下图

 根据上面的方法我们主要看下重要的一些实现

1.initComponent()

该方法是初始化EurekaInstanceConfig和InstanceInfo对象,这个方法主要用在非bean注入方式的时候,在获取InstanceInfo对象对象的时候,我们可以了解到EurekaConfigBasedInstanceInfoProvider类是单例模式的,同时get()方法是同步实现的。

2.StatusChangeListener

这个类相关的目前没有看到有任何的实现,所以相关的方法就不介绍了

3.refreshDataCenterInfoIfRequired()

这个方法从名称可以知道是刷新数据中心信息的,它用于表示新的数据连接地址被配置了,把当前实例对象设置为脏数据,然后在相应的应用引用的时候重新进行配置

public void refreshDataCenterInfoIfRequired() {
    String existingAddress = instanceInfo.getHostName();

    String existingSpotInstanceAction = null;
    if (instanceInfo.getDataCenterInfo() instanceof AmazonInfo) {
        existingSpotInstanceAction = ((AmazonInfo) instanceInfo.getDataCenterInfo()).get(AmazonInfo.MetaDataKey.spotInstanceAction);
    }

    String newAddress;
    if (config instanceof RefreshableInstanceConfig) {
        // Refresh data center info, and return up to date address
        newAddress = ((RefreshableInstanceConfig) config).resolveDefaultAddress(true);
    } else {
        newAddress = config.getHostName(true);
    }
    String newIp = config.getIpAddress();

    if (newAddress != null && !newAddress.equals(existingAddress)) {
        logger.warn("The address changed from : {} => {}", existingAddress, newAddress);
        updateInstanceInfo(newAddress, newIp);
    }

    if (config.getDataCenterInfo() instanceof AmazonInfo) {
        String newSpotInstanceAction = ((AmazonInfo) config.getDataCenterInfo()).get(AmazonInfo.MetaDataKey.spotInstanceAction);
        if (newSpotInstanceAction != null && !newSpotInstanceAction.equals(existingSpotInstanceAction)) {
            logger.info(String.format("The spot instance termination action changed from: %s => %s",
                    existingSpotInstanceAction,
                    newSpotInstanceAction));
            updateInstanceInfo(null , null );
        }
    }
}

private void updateInstanceInfo(String newAddress, String newIp) {
    // :( in the legacy code here the builder is acting as a mutator.
    // This is hard to fix as this same instanceInfo instance is referenced elsewhere.
    // We will most likely re-write the client at sometime so not fixing for now.
    InstanceInfo.Builder builder = new InstanceInfo.Builder(instanceInfo);
    if (newAddress != null) {
        builder.setHostName(newAddress);
    }
    if (newIp != null) {
        builder.setIPAddr(newIp);
    }
    builder.setDataCenterInfo(config.getDataCenterInfo());
    instanceInfo.setIsDirty();
}

3.refreshLeaseInfoIfRequired()

这个方法是指过期时间的刷新,当配置的过期时间与默认配置的不相同时就进行刷新操作。

public void refreshLeaseInfoIfRequired() {
    LeaseInfo leaseInfo = instanceInfo.getLeaseInfo();
    if (leaseInfo == null) {
        return;
    }
    int currentLeaseDuration = config.getLeaseExpirationDurationInSeconds();
    int currentLeaseRenewal = config.getLeaseRenewalIntervalInSeconds();
    if (leaseInfo.getDurationInSecs() != currentLeaseDuration || leaseInfo.getRenewalIntervalInSecs() != currentLeaseRenewal) {
        LeaseInfo newLeaseInfo = LeaseInfo.Builder.newBuilder()
                .setRenewalIntervalInSecs(currentLeaseRenewal)
                .setDurationInSecs(currentLeaseDuration)
                .build();
        instanceInfo.setLeaseInfo(newLeaseInfo);
        instanceInfo.setIsDirty();
    }
}

    

 以上就是本节的主要内容,我们主要了解了EurekaServiceRegistry和ApplicationInfoManager 这2个类的注入,后面章节我们继续剩下的类的注入讲解。

 
 
 

猜你喜欢

转载自357029540.iteye.com/blog/2440048
今日推荐