本文已参与「新人创作礼」活动,一起开启掘金创作之路。
服务端实例构造
初始化 ApplicationInfoManager
Application
Application:微服务架构中的一个服务,作为服务向 eureka server 注册。此时需要一个 eureka-client 提供功能。application 可以理解为 一个 eureka-client
// 获取 应用信息管理器
applicationInfoManager = new ApplicationInfoManager(
// eureka-client 实例配置 实例
instanceConfig,
// 基于 eureka-client 实例配置 实例 获取 InstanceInfo 实例信息 实例
new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());
EurekaInstanceConfig
EurekaInstanceConfig:将eureka-client.properties文件中的配置加载到ConfigurationManager中,基于EurekaInstanceConfig对外提供获取eureka-client.properties配置项的方法。
// 获取 eureka-client 实例配置 实例
EurekaInstanceConfig instanceConfig =
// 判断是否是 云服务。默认环境是test
isCloud(ConfigurationManager.getDeploymentContext()) ?
// 实例化 云实例配置
new CloudInstanceConfig() :
// 实例化 自定义数据中心实例配置
new MyDataCenterInstanceConfig();
MyDataCenterInstanceConfig
package com.netflix.appinfo;
@Singleton
@ProvidedBy(MyDataCenterInstanceConfigProvider.class)
public class MyDataCenterInstanceConfig extends PropertiesInstanceConfig implements EurekaInstanceConfig {
public MyDataCenterInstanceConfig() {
}
}
PropertiesInstanceConfig
package com.netflix.appinfo;
public abstract class PropertiesInstanceConfig extends AbstractInstanceConfig implements EurekaInstanceConfig {
protected final String namespace;
protected final DynamicPropertyFactory configInstance;
private String appGrpNameFromEnv;
public PropertiesInstanceConfig() {
this(CommonConstants.DEFAULT_CONFIG_NAMESPACE);
}
public PropertiesInstanceConfig(String namespace) {
this(namespace, new DataCenterInfo() {
@Override
public Name getName() {
return Name.MyOwn;
}
});
}
public PropertiesInstanceConfig(String namespace, DataCenterInfo info) {
super(info);
this.namespace = namespace.endsWith(".")
? namespace
: namespace + ".";
appGrpNameFromEnv = ConfigurationManager.getConfigInstance()
.getString(FALLBACK_APP_GROUP_KEY, Values.UNKNOWN_APPLICATION);
// CONFIG_FILE_NAME = "eureka-client";
this.configInstance = Archaius1Utils.initConfig(CommonConstants.CONFIG_FILE_NAME);
}
CommonConstants
package com.netflix.discovery;
/**
* @author David Liu
*/
public final class CommonConstants {
public static final String CONFIG_FILE_NAME = "eureka-client";
public static final String DEFAULT_CONFIG_NAMESPACE = "eureka";
}
Archaius1Utils
package com.netflix.discovery.internal.util;
public final class Archaius1Utils {
private static final Logger logger = LoggerFactory.getLogger(Archaius1Utils.class);
private static final String ARCHAIUS_DEPLOYMENT_ENVIRONMENT = "archaius.deployment.environment";
private static final String EUREKA_ENVIRONMENT = "eureka.environment";
public static DynamicPropertyFactory initConfig(String configName) {
DynamicPropertyFactory configInstance = DynamicPropertyFactory.getInstance();
DynamicStringProperty EUREKA_PROPS_FILE = configInstance.getStringProperty("eureka.client.props", configName);
String env = ConfigurationManager.getConfigInstance().getString(EUREKA_ENVIRONMENT, "test");
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, env);
String eurekaPropsFile = EUREKA_PROPS_FILE.get();
try {
ConfigurationManager.loadCascadedPropertiesFromResources(eurekaPropsFile);
} catch (IOException e) {
logger.warn(
"Cannot find the properties specified : {}. This may be okay if there are other environment "
+ "specific properties or the configuration is installed with a different mechanism.",
eurekaPropsFile);
}
return configInstance;
}
}
InstanceInfo
InstanceInfo: eureka-client实例信息 实例
基于EurekaInstanceConfig通过构造器模式构造InstanceInfo实例。
包含租约信息
EurekaInstanceConfig = MyDataCenterInstanceConfig -> PropertiesInstanceConfig -> AbstractInstanceConfig -> EurekaInstanceConfig
package com.netflix.appinfo.providers;
import javax.inject.Singleton;
import javax.inject.Provider;
import java.util.Map;
import com.google.inject.Inject;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.InstanceInfo.PortType;
import com.netflix.appinfo.LeaseInfo;
import com.netflix.appinfo.RefreshableInstanceConfig;
import com.netflix.appinfo.UniqueIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* InstanceInfo provider that constructs the InstanceInfo this this instance using
* EurekaInstanceConfig.
* <p>
* This provider is @Singleton scope as it provides the InstanceInfo for both DiscoveryClient
* and ApplicationInfoManager, and need to provide the same InstanceInfo to both.
*
* @author elandau
*/
@Singleton
public class EurekaConfigBasedInstanceInfoProvider implements Provider<InstanceInfo> {
private static final Logger LOG =
LoggerFactory.getLogger(EurekaConfigBasedInstanceInfoProvider.class);
private final EurekaInstanceConfig config;
private InstanceInfo instanceInfo;
@Inject(optional = true)
private VipAddressResolver vipAddressResolver = null;
@Inject
public EurekaConfigBasedInstanceInfoProvider(EurekaInstanceConfig config) {
this.config = config;
}
/**
* 构造器模式 构造 eureka-client实例信息 实例
*
* @return
*/
@Override
public synchronized InstanceInfo get() {
if (instanceInfo == null) {
// eureka-client 实例信息 实例为null
// 基于 eureka-client 实例配置信息 构建 租约信息
// 续约间隔,单位是秒。默认30s
// 租约过期自动摘除间隔,单位是秒。默认90s
// Build the lease information to be passed to the server based on config
LeaseInfo.Builder leaseInfoBuilder =
LeaseInfo.Builder.newBuilder().setRenewalIntervalInSecs(config.getLeaseRenewalIntervalInSeconds()).setDurationInSecs(config.getLeaseExpirationDurationInSeconds());
// 获取vip地址解析器
if (vipAddressResolver == null) {
vipAddressResolver = new Archaius1VipAddressResolver();
}
// 获取 eureka-client 实例信息构造器 实例
// Builder the instance information to be registered with eureka server
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder(vipAddressResolver);
// 为InstanceInfo设置合适的id,
// set the appropriate id for the InstanceInfo, falling back to datacenter Id if
// applicable, else hostname
String instanceId = config.getInstanceId();
// dataCenterInfo 默认是 MyOwn
DataCenterInfo dataCenterInfo = config.getDataCenterInfo();
if (instanceId == null || instanceId.isEmpty()) {
if (dataCenterInfo instanceof UniqueIdentifier) {
instanceId = ((UniqueIdentifier) dataCenterInfo).getId();
} else {
instanceId = config.getHostName(false); // 192.168.1.2
}
}
String defaultAddress;
if (config instanceof RefreshableInstanceConfig) {
// Refresh AWS data center info, and return up to date address
defaultAddress = ((RefreshableInstanceConfig) config).resolveDefaultAddress(false);
} else {
// config instanceof EurekaInfoConfig
defaultAddress = config.getHostName(false); // 192.168.1.2
}
// fail safe
if (defaultAddress == null || defaultAddress.isEmpty()) {
defaultAddress = config.getIpAddress(); // 192.168.1.2
}
builder.setNamespace(
// eureka.
config.getNamespace())
.setInstanceId(
// 192.168.1.2
instanceId)
.setAppName(
// eureka.name=eureka
config.getAppname())
.setAppGroupName(
// eureka.appGroup = null
config.getAppGroupName())
.setDataCenterInfo(
// new DataCenterInfo() {
// @Override
// public Name getName() {
// return Name.MyOwn;
// }
// };
config.getDataCenterInfo())
.setIPAddr(
// 192.168.1.2
config.getIpAddress())
.setHostName(
// 192.168.1.2
defaultAddress)
.setPort(
// eureka.port = 8080
config.getNonSecurePort())
.enablePort(PortType.UNSECURE,
// eureka.port.enabled = treu
config.isNonSecurePortEnabled())
.setSecurePort(
// eureka.securePort = 443
config.getSecurePort())
.enablePort(PortType.SECURE,
// eureka.securePort.enabled = false
config.getSecurePortEnabled())
.setVIPAddress(config.getVirtualHostName())
.setSecureVIPAddress(config.getSecureVirtualHostName())
.setHomePageUrl(config.getHomePageUrlPath(), config.getHomePageUrl())
.setStatusPageUrl(config.getStatusPageUrlPath(), config.getStatusPageUrl())
.setASGName(config.getASGName())
.setHealthCheckUrls(config.getHealthCheckUrlPath(),
config.getHealthCheckUrl(), config.getSecureHealthCheckUrl());
// Start off with the STARTING state to avoid traffic
// eureka.traffic.enabled = false
if (!config.isInstanceEnabledOnit()) {
InstanceStatus initialStatus = InstanceStatus.STARTING;
LOG.info("Setting initial instance status as: " + initialStatus);
builder.setStatus(initialStatus);
} else {
LOG.info("Setting initial instance status as: {}. This may be too early for the " + "instance to advertise " + "itself as available. You would instead want to control this " + "via a healthcheck handler.", InstanceStatus.UP);
}
//
// 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 = builder.build();
instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
}
return instanceInfo;
}
}
初始化 eureka-client
初始化 eureka-server 内部的一个 eureka-client(用来与其他 eureka-server 节点进行 注册和通信)