前言
本篇文章主要解读Eureka-Client初始化的相关源码,文章较长,请谨慎点击!
EurekaInstanceConfig
EurekaInstanceConfig简介
所属包:com.netflix.appinfo.EurekaInstanceConfig
,Eureka 应用实例配置接口(Application Provider,Application Consumer)。
EurekaInstanceConfig源码
博主已添加中文注释,点击查看。
EurekaInstanceConfig重要属性或者重要方法
getInstanceId()
获取实例id,组成结构为${spring.application.name}:${spring.application.instance_id:${random.value}}
默认为null。geAppName()
获取应用名,默认为”unknown”。
getLeaseRenewalIntervalInSeconds()
获取租约续约频率,单位为秒。默认为30s。应用发送心跳给Eureka-Server进行续约(告诉Eureka-Server自己还活着)。getLeaseExpirationDurationInSeconds()
获取租约过期时间,单位为秒。默认为90s。如果超过该时间,应用还没有向Eureka-Server发送心跳,那该租约就过期了,Eureka-Serever会进行应用移除。getMetadataMap()
获取实例的元数据。如果你想自定义一些数据,在各服务之间使用,就需要该方法。getHealthCheckUrlPath()
,getHealthCheckUrl()
,getSecureHealthCheckUrl()
健康检查相关的几个方法。getNamespace()
获取命名空间,已配置对应的eureka属性,默认为eureka
。
AbstractInstanceConfig
AbstractInstanceConfig简介
所属包:com.netflix.appinfo.AbstractInstanceConfig
,Eureka 应用实例配置抽象基类,主要实现一些相对通用的配置
AbstractInstanceConfig源码
博主已添加中文注释,点击查看。
AbstractInstanceConfig重要属性或者重要方法
- 主要设置一些基础的属性,以及对应的get/set方法
getHostInfo()
获取本地服务器的主机名和主机IP地址
PropertiesInstanceConfig
PropertiesInstanceConfig简介
所属包:com.netflix.appinfo.PropertiesInstanceConfig
,通过配置文件进行Eureka实例配置的抽象基类
PropertiesInstanceConfig源码
博主已添加中文注释,点击查看。
PropertiesInstanceConfig重要属性或者重要方法
namespace
命名空间。configInstance
配置文件,基于Netflix Archaius 1.x 实现读取配置文件。基于Netflix Archaius 2.x 的还在开发中。appGrpNameFromEnv
从环境变量中获取应用分组,ConfigurationManager.getConfigInstance
获取当前的系统范围配置。Archaius1Utils.initConfig(CommonConstants.CONFIG_FILE_NAME)
,CommonConstants.CONFIG_FILE_NAME
为eureka-client
,Archaius1Utils.initConfig
方法源码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34public 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();
// 配置文件名,如果configName没有配置,即为CommonConstants.CONFIG_FILE_NAME("eureka-client")
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 {
//读取配置文件到环境变量,首先读取 ${eureka.client.props} 对应的配置文件;然后读取 ${eureka.client.props}-${eureka.environment} 对应的配置文件。若有相同属性,进行覆盖。
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;
}
}其他实现方法基本类似,都是从配置文件中获取值,举一个例子:
isInstanceEnabledOnit()
:从配置文件中获取是否在实例初始化的时候开启,并传一个默认值(这里是父类AbstractInstanceConfig中实现的方法),namespace的属性key都在PropertyBasedInstanceConfigConstants中
MyDataCenterInstanceConfig
MyDataCenterInstanceConfig简介
所属包:com.netflix.appinfo.MyDataCenterInstanceConfig
,Eureka应用实例配置实现类
MyDataCenterInstanceConfig源码
1 | public class MyDataCenterInstanceConfig extends PropertiesInstanceConfig implements EurekaInstanceConfig { |
InstanceInfo
InstanceInfo简介
所属包:com.netflix.appinfo.InstanceInfo
,应用实例信息。Eureka-Client 向 Eureka-Server 注册该对象信息。注册成功后,可以被其他 Eureka-Client 发现。Eureka通过com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider
基于EurekaInstanceConfig
创建InstanceInfo
。
EurekaConfigBasedInstanceInfoProvider源码
博主已添加中文注释,点击查看。
EurekaConfigBasedInstanceInfoProvider重要属性或者重要方法
基本上每个属性和每个方法都添加了注释
其中vip地址解析器源码如下:
1
2
3
4
5
6
7
8
9
10public interface VipAddressResolver {
/**
* Convert <code>VIPAddress</code> by substituting environment variables if necessary.
*
* @param vipAddressMacro the macro for which the interpolation needs to be made.
* @return a string representing the final <code>VIPAddress</code> after substitution.
*/
String resolveDeploymentContextBasedVipAddresses(String vipAddressMacro);
}实现类源码(Archaius1实现,Archaius2还在开发中):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public class Archaius1VipAddressResolver implements VipAddressResolver {
private static final Logger logger = LoggerFactory.getLogger(Archaius1VipAddressResolver.class);
private static final Pattern VIP_ATTRIBUTES_PATTERN = Pattern.compile("\\$\\{(.*?)\\}");
public String resolveDeploymentContextBasedVipAddresses(String vipAddressMacro) {
if (vipAddressMacro == null) {
return null;
}
String result = vipAddressMacro;
//匹配${(.*?)}
Matcher matcher = VIP_ATTRIBUTES_PATTERN.matcher(result);
while (matcher.find()) {
String key = matcher.group(1);
String value = DynamicPropertyFactory.getInstance().getStringProperty(key, "").get();
logger.debug("att:{}", matcher.group());
logger.debug(", att key:{}", key);
logger.debug(", att value:{}", value);
logger.debug("");
//将${(.*?)}替换为配置文件中对应的value
result = result.replaceAll("\\$\\{" + key + "\\}", value);
matcher = VIP_ATTRIBUTES_PATTERN.matcher(result);
}
return result;
}
}
ApplicationInfoManager
ApplicationInfoManager简介
所属包:com.netflix.appinfo.ApplicationInfoManager
,应用信息管理类,由InstanceInfo
和EurekaInstanceConfig
生成。
ApplicationInfoManager源码
博主已添加中文注释,点击查看。
EurekaClientConfig
EurekaClientConfig简介
所属包:com.netflix.discovery.EurekaClientConfig
,Eureka-Client 配置接口,获取连接的 Eureka-Server 的地址、获取服务提供者列表的频率、注册自身为服务提供者的频率等等。
EurekaClientConfig源码
博主已添加中文注释,点击查看。
EurekaClientConfig重要属性或者重要方法
getRegion()
,getAvailabilityZones()
:region和zone(或者Availability Zone)均是AWS的概念。在非AWS环境下,我们可以简单地将region理解为Eureka集群,zone理解成机房。Spring Cloud中默认的region是us-east-1 。具体可查看《周立 —— Region、Zone解析》。getEurekaServerServiceUrls()
:获取Eureka-Server的Url集合- 从Eureka-Server获取注册信息的相关方法:
getRegistryFetchIntervalSeconds()
:获取注册信息的时间间隔,单位为秒。默认为30sgetEurekaServiceUrlPollIntervalSeconds()
:向Eureka-Server获取Eureka服务地址的变化时间间隔,单位为秒。默认为 5 * 60 * 1000 sgetEurekaServerReadTimeoutSeconds()
:获取Eureka-Server读取超时时间,单位为秒。默认为8sgetBackupRegistryImpl()
:获取备份注册中心实现类。默认为nullshouldPreferSameZoneEureka()
:相同Zone的Eureka是否优先。默认为trueshouldDisableDelta()
:是否使用增量形式获取注册信息。默认为falsefetchRegistryForRemoteRegions()
:获取远程区域的注册信息。默认为nullshouldFilterOnlyUpInstances()
:是否只获取Up(启动)状态的实例。默认为trueshouldFetchRegistry()
:是否从Eureka-Server获取注册信息。默认为truegetRegistryRefreshSingleVipAddress()
:获取单个vip地址(虚拟IP地址)的注册信息。默认为nullgetCacheRefreshExecutorThreadPoolSize()
:获取注册信息缓存刷新的线程池大小。默认为5getCacheRefreshExecutorExponentialBackOffBound()
:获取注册信息缓存刷新执行超时后的延迟重试时间的最大倍数。默认为10
- 向Eureka-Server注册自身服务的相关方法:
getInstanceInfoReplicationIntervalSeconds()
:获取向Eureka-Server同步实例信息的时间间隔,单位为秒。默认为30sgetInitialInstanceInfoReplicationIntervalSeconds()
:获取最初向Eureka-Server同步实例信息的时间间隔,单位为秒。默认为40sgetEurekaServerConnectTimeoutSeconds()
:获取Eureka-Server连接超时时间,单位为秒。默认为5sshouldRegisterWithEureka()
:是否向Eureka-Server注册自身服务。默认为trueshouldUnregisterOnShutdown()
:当Eureka-Server关闭的时候,是否注销自己的服务。默认为truegetHeartbeatExecutorThreadPoolSize()
:获取心跳检测执行的线程池大小。默认为5getHeartbeatExecutorExponentialBackOffBound()
:获取心跳检测执行超时后的延迟重试时间的最大倍数。默认为10shouldEnforceRegistrationAtInit()
:是否在实例初始化的时候进行注册。默认为false
DefaultEurekaClientConfig
DefaultEurekaClientConfig简介
所属包:com.netflix.discovery.DefaultEurekaClientConfig
,基于配置文件的Eureka-Client配置实现类。
DefaultEurekaClientConfig源码
博主已添加中文注释,点击查看。
DefaultEurekaClientConfig重要属性或者重要方法
- 其中属性和构造方法基本上都加了中文注释。
其他实现方法基本类似,都是从配置文件中获取值,举一个例子:
`getRegistryFetchIntervalSeconds()`:从配置文件中获取读取注册信息的时间间隔,并传一个默认值(这里是30),namespace后面的属性key都在PropertyBasedClientConfigConstants中。
DefaultEurekaClientConfigProvider
DefaultEurekaClientConfigProvider简介
所属包:com.netflix.discovery.providers.DefaultEurekaClientConfigProvider
,创建 DefaultEurekaClientConfig 的工厂 。
DefaultEurekaClientConfigProvider源码
1 | public class DefaultEurekaClientConfigProvider implements Provider<EurekaClientConfig> { |
很简单的一个类,不做过多的分析。
EurekaTransportConfig
EurekaTransportConfig简介
所属包:com.netflix.discovery.shared.transport.EurekaTransportConfig
,Eureka网络传输配置接口。
EurekaTransportConfig源码
博主已添加中文注释,点击查看。
EurekaTransportConfig重要属性或者重要方法
getSessionedClientReconnectIntervalSeconds()
:Eureka-Client 会话重新连接的时间间隔,单位为秒,默认为20 * 60s。getRetryableClientQuarantineRefreshPercentage()
:请求失败的Eureka-Client隔离集合占Eureka-Client总数的占比,超过该比例会进行清空,默认为0.66。- Endpoint相关:
getAsyncResolverRefreshIntervalMs()
:异步解析 EndPoint 集群频率,单位为毫秒。默认为5 * 60 * 1000ms。getAsyncResolverWarmUpTimeoutMs()
:异步解析器预热解析 EndPoint 集群超时时间,单位为毫秒。默认为5000s。getAsyncExecutorThreadPoolSize()
:异步线程池大小,默认为5。
DefaultEurekaTransportConfig
DefaultEurekaTransportConfig简介
所属包:com.netflix.discovery.shared.transport.DefaultEurekaTransportConfig
,基于配置文件的网络传输配置实现类 。
DefaultEurekaTransportConfig源码
博主已添加中文注释,点击查看。
DefaultEurekaTransportConfig重要属性或者重要方法
- 其他实现方法基本类似,都是从配置文件中获取值,举一个例子:
getSessionedClientReconnectIntervalSeconds()
:Eureka-Client 会话重新连接的时间间隔,并传一个默认值(这里是20 * 60),namespace的属性key都在PropertyBasedTransportConfigConstants中。
LookupService
LookupService简介
所属包:com.netflix.discovery.shared.LookupService
,查找服务接口,可以获取应用集合和应用实例集合。
- 在 Eureka-Client 里,EurekaClient 继承该接口。
- 在 Eureka-Server 里,
com.netflix.eureka.registry.InstanceRegistry
继承该接口。
LookupService源码
博主已添加中文注释,点击查看。
EurekaClient
EurekaClient简介
所属包:com.netflix.discovery.EurekaClient
,Eureka-Client接口 。
EurekaClient源码
博主已添加中文注释,点击查看。
EurkeaClient重要属性或者重要方法
- 获取应用集合:
getApplicationsForARegion(@Nullable String region)
:获取指定区域中的Applications。getApplications(String serviceUrl)
:获取指定的Eureka服务地址中注册的应用集合。
- 获取应用实例集合:
getInstancesByVipAddress(String vipAddress, boolean secure)
:获取指定VIP地址的实例列表。getInstancesByVipAddress(String vipAddress, boolean secure, @Nullable String region)
:获取指定VIP地址和区域的实例信息列表。getInstancesByVipAddressAndAppName(String vipAddress, String appName, boolean secure)
:获取指定VIP地址和appName的实例信息列表。
getAllKnownRegions()
:获取所有已知的区域。getInstanceRemoteStatus()
:获取实例状态。registerHealthCheck()
:Eureka-Client注册健康检查。getHealthCheckHandler()
:获取健康监测处理器。registerEventListener()
:Eureka-Client注册事件监听。unregisterEventListener()
:Eureka-Client取消事件监听注册。getEurekaClientConfig()
:获取Eureka-Client配置。getApplicationInfoManager()
:获取应用信息管理器。
DiscoveryClient
DiscoveryClient简介
所属包:com.netflix.discovery.DiscoveryClient
,EurekaClient接口的实现类,用于与 Eureka-Server 交互。包含方法:
- 向 Eureka-Server 注册自身服务
- 向 Eureka-Server 续约自身服务
- 向 Eureka-Server 取消自身服务,当关闭时
- 从 Eureka-Server 查询应用集合和应用实例信息
- 本文主要介绍DiscoveryClient的初始化,其他方法后续文章会有介绍
DiscoveryClient源码
博主已添加中文注释,点击查看。
DiscoveryClient重要属性或者重要方法
构造函数:
1 |
|
参数:
ApplicationInfoManager
:应用信息管理类,具体可查看ApplicationInfoManager
小结。EurekaClientConfig
:Eureka-Client 配置接口,获取连接的 Eureka-Server 的地址、获取服务提供者列表的频率、注册自身为服务提供者的频率等等,具体可查看EurekaClientConfig
小结。AbstractDiscoveryClientOptionalArgs
:DiscoveryClient 可选参数抽象基类。该参数是选填参数,实际生产中很少使用,源码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53public abstract class AbstractDiscoveryClientOptionalArgs<T> {
/**
* 健康检查回调的工厂
*/
Provider<HealthCheckCallback> healthCheckCallbackProvider;
/**
* 健康检查处理器的工厂
*/
Provider<HealthCheckHandler> healthCheckHandlerProvider;
/**
* 向Eureka-Server注册之前的处理器
*/
PreRegistrationHandler preRegistrationHandler;
/**
* Jersey 过滤器集合
*/
Collection<T> additionalFilters;
/**
* Jersey 客户端
*/
EurekaJerseyClient eurekaJerseyClient;
/**
* 生成 Jersey 客户端工厂
*/
TransportClientFactory transportClientFactory;
/**
* 生成 Jersey 客户端工厂
*/
TransportClientFactories transportClientFactories;
/**
* Eureka 事件监听集合
*/
private Set<EurekaEventListener> eventListeners;
/**
* ssl
*/
private Optional<SSLContext> sslContext = Optional.empty();
/**
* 主机认证
*/
private Optional<HostnameVerifier> hostnameVerifier = Optional.empty();
//省略set方法
}Provider<BackupRegistry>
:备份注册中心接口,当 Eureka-Client 启动时,无法从 Eureka-Server 读取注册信息,就从备份注册中心读取注册信息 ,源码如下:1
2
3
4
5
6
7(NotImplementedRegistryImpl.class)
public interface BackupRegistry {
Applications fetchRegistry();
Applications fetchRegistry(String[] includeRemoteRegions);
}实现类源码如下(可以看出暂未提供合适的实现):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class NotImplementedRegistryImpl implements BackupRegistry {
/**
* 获取应用注册信息
*
* @return 应用列表对象 (默认为null)
*/
public Applications fetchRegistry() {
return null;
}
/**
* 获取应用注册信息
*
* @param includeRemoteRegions 远程区域列表
* @return 应用列表对象(默认为null)
*/
public Applications fetchRegistry(String[] includeRemoteRegions) {
return null;
}
}
具体逻辑可查看源码,博主已添加中文注释
总结
我们可以看到 EurekaClient 的创建,先是通过 EurekaInstanceConfig 生成 InstanceInfo,再通过 EurekaInstanceConfig 和 InstanceInfo 生成 ApplicationInfoManager,最后 EurekaClientConfig 和 ApplicationInfoManager 生成 EurekaClient。
欢迎关注博主其他的文章。