理解微服务注册到Eureka Server上的过程(以appname为例)

阅读本文你将了解

  • 微服务注册到Eureka Server上的粗粒度过程
  • 为什么appname是大写。
  • appName的配置:spring.application.name与eureka.instance.appname,及它们的优先级。

Prepare

首先解释一下什么是appname

10-2.png

图中的MICROSERVICE-PROVIDER-USER就是appname。下面我们来分析一下它的详细逻辑。

分析

(1) 首先找到:org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration.EurekaClientConfiguration.eurekaApplicationInfoManager(EurekaInstanceConfig)

里面有以下代码:

@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {
  InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
  return new ApplicationInfoManager(config, instanceInfo);
}

从中,可以看到,该方法调用了new InstanceInfoFactory().create(config);

(2) 跟进org.springframework.cloud.netflix.eureka.InstanceInfoFactory.create(EurekaInstanceConfig) ,可以看到以下代码:

public InstanceInfo create(EurekaInstanceConfig config) {
    LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder()
            .setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds())
            .setDurationInSecs(config.getLeaseExpirationDurationInSeconds());

    // Builder the instance information to be registered with eureka
    // server
    InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();

    String namespace = config.getNamespace();
    if (!namespace.endsWith(".")) {
        namespace = namespace + ".";
    }
    builder.setNamespace(namespace).setAppName(config.getAppname())
            .setInstanceId(config.getInstanceId())
            .setAppGroupName(config.getAppGroupName())
            .setDataCenterInfo(config.getDataCenterInfo())
            .setIPAddr(config.getIpAddress()).setHostName(config.getHostName(false))
            .setPort(config.getNonSecurePort())
            .enablePort(InstanceInfo.PortType.UNSECURE,
                    config.isNonSecurePortEnabled())
            .setSecurePort(config.getSecurePort())
            .enablePort(InstanceInfo.PortType.SECURE, config.getSecurePortEnabled())
            .setVIPAddress(config.getVirtualHostName())
            .setSecureVIPAddress(config.getSecureVirtualHostName())
            .setHomePageUrl(config.getHomePageUrlPath(), config.getHomePageUrl())
            .setStatusPageUrl(config.getStatusPageUrlPath(),
                    config.getStatusPageUrl())
            .setHealthCheckUrls(config.getHealthCheckUrlPath(),
                    config.getHealthCheckUrl(), config.getSecureHealthCheckUrl())
            .setASGName(config.getASGName());

    // Start off with the STARTING state to avoid traffic
    if (!config.isInstanceEnabledOnit()) {
        InstanceInfo.InstanceStatus initialStatus = InstanceInfo.InstanceStatus.STARTING;
        if (log.isInfoEnabled()) {
            log.info("Setting initial instance status as: " + initialStatus);
        }
        builder.setStatus(initialStatus);
    }
    else {
        if (log.isInfoEnabled()) {
            log.info("Setting initial instance status as: "
                    + InstanceInfo.InstanceStatus.UP
                    + ". This may be too early for the instance to advertise itself as available. "
                    + "You would instead want to control this via a healthcheck handler.");
        }
    }

    // Add any user-specific metadata information
    for (Map.Entry mapEntry : config.getMetadataMap().entrySet()) {
        String key = mapEntry.getKey();
        String value = mapEntry.getValue();
        builder.add(key, value);
    }

    InstanceInfo instanceInfo = builder.build();
    instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
    return instanceInfo;
}

代码比较长,但是不难看出,该代码是在通过传入的配置,去构建一个InstanceInfo,也就是某个微服务实例的各种信息。

在代码中,找到以下代码:

builder.setNamespace(namespace).setAppName(config.getAppname())
                .setInstanceId(config.getInstanceId())

我们不妨跟进setAppname中看看。

(3) 查看com.netflix.appinfo.InstanceInfo.Builder.setAppName(String)

public Builder setAppName(String appName) {
  result.appName = StringCache.intern(appName.toUpperCase(Locale.ROOT));
  return this;
}

我们可以看到,是该方法将appName转大写了。

(4) 回到

builder.setNamespace(namespace).setAppName(config.getAppname())
                .setInstanceId(config.getInstanceId())

这段代码,通过DEBUG,我们可以看到代码中的config,是

org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean

(5) 查看该类,我们会发现这正式Eureka Instance的配置类。因此,我们可以使用eureka.instance.appname去配置appName。

@Data
@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware, InitializingBean {

    private static final String UNKNOWN = "unknown";

    @Getter(AccessLevel.PRIVATE)
    @Setter(AccessLevel.PRIVATE)
    private HostInfo hostInfo;

    @Getter(AccessLevel.PRIVATE)
    @Setter(AccessLevel.PRIVATE)
    private InetUtils inetUtils;

    /**
     * Get the name of the application to be registered with eureka.
     */
    private String appname = UNKNOWN;

(6) 那么,为什么我们可以通过spring.application.name去配置微服务的appName呢?代码在这里:

org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean.afterPropertiesSet()

@Override
public void afterPropertiesSet() throws Exception {
    RelaxedPropertyResolver springPropertyResolver = new RelaxedPropertyResolver(this.environment, "spring.application.");
    String springAppName = springPropertyResolver.getProperty("name");
    if(StringUtils.hasText(springAppName)) {
        setAppname(springAppName);
        setVirtualHostName(springAppName);
        setSecureVirtualHostName(springAppName);
    }
}

经过以上分析,我们可以看到spring.application.name的优先级比eureka.instance.appname高。例如:

server:
  port: 8000
spring:
  application:
    name: microservice-provider-user
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    appname: abc
    prefer-ip-address: true

两者都配置的时候,注册到Eureka Server上的appname是microservice-provider-user

本文首发

http://www.itmuch.com/spring-cloud-code-read/spring-cloud-code-read-eureka-registry-appname/

干货分享

理解微服务注册到Eureka Server上的过程(以appname为例)_第1张图片
全是干货

你可能感兴趣的:(理解微服务注册到Eureka Server上的过程(以appname为例))