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

阅读本文你将了解

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

Prepare

首先解释一下什么是appname

图中的CONFIG-SERVER,GATEWAY,IOT 就是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<String, String> 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: aaa
    eureka:
        client:
            serviceUrl:
            defaultZone: http://localhost:8761/eureka/
            instance:
                appname: bbb
                prefer-ip-address: true

两者都配置的时候,注册到Eureka Server上的appname是aaa

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值