1. EurekaServer启动过程
@EnableEurekaServer
@SpringBootApplication
public class Service01Application {
public static void main(String[] args) {
SpringApplication.run(Service01Application.class, args);
}
}
通过@EnableEurekaServer注解开启EurekaServer配置,下面我们通过注解一步步的来看EurekaServer的初始化过程。
/**
* 注释以激活Eureka服务器相关配置。
* Annotation to activate Eureka Server related configuration. {@link EurekaServerAutoConfiguration}
* @author Dave Syer
* @author Biju Kunjummen
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}
该注解的作用很简单,激活EurekaServer,这里主要分为两部分,EurekaServerMarkerConfiguration和EurekaServerAutoConfiguration
- EurekaServerMarkerConfiguration 负责添加标记bean以用来激活EurekaServerAutoConfiguration(源码很简单不粘贴了)
- EurekaServerAutoConfiguration EurekaServer自动配置类
该注解中并未引入EurekaServerAutoConfiguration类,那么该类是何时被初始化呢?打开EurekaServer工程下的resources–>MEAT-INFO–>spring-factories文件,该配置文件中有:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
SpringBoot会自动加载并将其实例化,EurekaServerAutoConfiguration类的代码比较长,我们只粘贴其注解部分:
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
...省略代码
}
- @Configuration --> 通过@Configuration+@Bean加载SpringBean
- @Import --> 导入EurekaServerInitializerConfiguration
- @ConditionalOnBean --> 当BeanFactory中存在指定bean的时候才匹配
- @EnableConfigurationProperties --> 使标注了@ConfigurationProperties注解的类生效,这里即EurekaDashboardProperties和InstanceRegistryProperties
- @PropertySource --> 资源文件
对于EurekaServerAutoConfiguration的解析也要分为两部分,第一:其本身包含的代码部分。;第二:注解部分。
先来看第一部分:该部分主要包含了对静态代码块、静态内部类、各种bean的注入操作。
1.1 静态内部类初始化
@Configuration
protected static class EurekaServerConfigBeanConfiguration {
@Bean
@ConditionalOnMissingBean
public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
EurekaServerConfigBean server = new EurekaServerConfigBean();
// 是否注册到Eureka
if (clientConfig.shouldRegisterWithEureka()) {
// Set a sensible default if we are supposed to replicate
server.setRegistrySyncRetries(5);
}
return server;
}
}
该类标注了@ConditionalOnMissingBean注解,即当当前BeanFactory中不包含EurekaServerConfig实例时,则创建一个EurekaServerConfig实例,该实例中包含了EurekaServer中的默认配置信息:
// 获取aws访问的id,主要用于弹性ip绑定,此配置是用于aws上的,默认为null
private String aWSAccessId;
// 获取aws私有秘钥,主要用于弹性ip绑定,此配置是用于aws上的,默认为null
private String aWSSecretKey;
// 获取服务器尝试绑定到候选的EIP的次数,默认为3
private int eIPBindRebindRetries = 3;
// 与上面的是同一作用,仅仅是稳定状态检查,默认为5 * 60 * 1000
private int eIPBindingRetryIntervalMs = 5 * MINUTES;
// 服务器检查ip绑定的时间间隔,单位为毫秒,默认为1 * 60 * 1000
private int eIPBindingRetryIntervalMsWhenUnbound = 1 * MINUTES;
// 自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,
// 即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
private boolean enableSelfPreservation = true;
// 阈值因子,默认是0.85,如果阈值比最小值大,则自我保护模式开启
private double renewalPercentThreshold = 0.85;
// 阈值更新的时间间隔,单位为毫秒,默认为15 * 60 * 1000
private int renewalThresholdUpdateIntervalMs = 15 * MINUTES;
// 集群里eureka节点的变化信息更新的时间间隔,单位为毫秒,默认为10 * 60 * 1000
private int peerEurekaNodesUpdateIntervalMs = 10 * MINUTES;
// 获取集群里服务器尝试复制数据的次数,默认为5
private int numberOfReplicationRetries = 5;
// 服务器节点的状态信息被更新的时间间隔,单位为毫秒,默认为30 * 1000
private int peerEurekaStatusRefreshTimeIntervalMs = 30 * 1000;
// 在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间,单位为毫秒,默认为1000 * 60 * 5
private int waitTimeInMsWhenSyncEmpty = 5 * MINUTES;
// 连接对等节点服务器复制的超时的时间,单位为毫秒,默认为200
private int peerNodeConnectTimeoutMs = 200;
// 读取对等节点服务器复制的超时的时间,单位为毫秒,默认为200
private int peerNodeReadTimeoutMs = 200;
// 获取对等节点上http连接的总数,默认为1000
private int peerNodeTotalConnections = 1000;
// 获取特定的对等节点上http连接的总数,默认为500
private int peerNodeTotalConnectionsPerHost = 500;
// http连接被清理之后服务器的空闲时间,默认为30秒
private int peerNodeConnectionIdleTimeoutSeconds = 30;
// 客户端保持增量信息缓存的时间,从而保证不会丢失这些信息,单位为毫秒,默认为3 * 60 * 1000
private long retentionTimeInMSInDeltaQueue = 3 * MINUTES;
// 清理任务程序被唤醒的时间间隔,清理过期的增量信息,单位为毫秒,默认为30 * 1000
private long deltaRetentionTimerIntervalInMs = 30 * 1000;
// 过期实例应该启动并运行的时间间隔,单位为毫秒,默认为60 * 1000
private long evictionIntervalTimerInMs = 60 * 1000;
// 查询AWS上ASG(自动缩放组)信息的超时值,单位为毫秒,默认为300
private int aSGQueryTimeoutMs = 300;
// 从AWS上更新ASG信息的时间间隔,单位为毫秒,默认为5 * 60 * 1000
private long aSGUpdateIntervalMs = 5 * MINUTES;
//缓存ASG信息的到期时间,单位为毫秒,默认为10 * 60 * 1000
private long aSGCacheExpiryTimeoutMs = 10 * MINUTES; // defaults to longer than the
// 当注册表信息被改变时,则其被保存在缓存中不失效的时间,默认为180秒
private long responseCacheAutoExpirationInSeconds = 180;
// 客户端的有效负载缓存应该更新的时间间隔,默认为30 * 1000毫秒
private long responseCacheUpdateIntervalMs = 30 * 1000;
// 目前采用的是二级缓存策略,一个是读写高速缓存过期策略,另一个没有过期只有只读缓存,默认为true,表示只读缓存
private boolean useReadOnlyResponseCache = true;
// 增量信息是否可以提供给客户端看,默认为false
private boolean disableDelta;
// 状态复制线程可以保持存活的空闲时间,默认为10分钟
private long maxIdleThreadInMinutesAgeForStatusReplication = 10;
// 被用于状态复制的线程的最小数目,默认为1
private int minThreadsForStatusReplication = 1;
// 被用于状态复制的线程的最大数目,默认为1
private int maxThreadsForStatusReplication = 1;
// 可允许的状态复制池备份复制事件的最大数量,默认为10000
private int maxElementsInStatusReplicationPool = 10000;
// 当时间变化实例是否跟着同步,默认为true
private boolean syncWhenTimestampDiffers = true;
// 当eureka服务器启动时尝试去获取集群里其他服务器上的注册信息的次数,默认为5
private int registrySyncRetries = 0;
// 当eureka服务器启动时获取其他服务器的注册信息失败时,会再次尝试获取,期间需要等待的时间,默认为30 * 1000毫秒
private long registrySyncRetryWaitMs = 30 * 1000;
// 复制池备份复制事件的最大数量,默认为10000
private int maxElementsInPeerReplicationPool = 10000;
// 复制线程可以保持存活的空闲时间,默认为15分钟
private long maxIdleThreadAgeInMinutesForPeerReplication = 15;
// 获取将被用于复制线程的最小数目,默认为5
private int minThreadsForPeerReplication = 5;
// 获取将被用于复制线程的最大数目,默认为20
private int maxThreadsForPeerReplication = 20;
// 尝试在丢弃复制事件之前进行复制的时间,默认为30000毫秒
private int maxTimeForReplication = 30000;
// 对集群中服务器节点的连接是否应该准备,默认为true
private boolean primeAwsReplicaConnections = true;
// 增量信息是否可以提供给客户端或一些远程地区,默认为false
private boolean disableDeltaForRemoteRegions;
// 连接到对等远程地eureka节点的超时时间,默认为1000毫秒
private int remoteRegionConnectTimeoutMs = 1000;
// 获取从远程地区eureka节点读取信息的超时时间,默认为1000毫秒
private int remoteRegionReadTimeoutMs = 1000;
// 获取远程地区对等节点上http连接的总数,默认为1000
private int remoteRegionTotalConnections = 1000;
// 获取远程地区特定的对等节点上http连接的总数,默认为500
private int remoteRegionTotalConnectionsPerHost = 500;
// http连接被清理之后远程地区服务器的空闲时间,默认为30秒
private int remoteRegionConnectionIdleTimeoutSeconds = 30;
// eureka服务器中获取的内容是否在远程地区被压缩,默认为true
private boolean gZipContentFromRemoteRegion = true;
// 针对远程地区发现的网址域名的map
private Map<String, String> remoteRegionUrlsWithName = new HashMap<>();
// 远程地区的URL列表
private String[] remoteRegionUrls;
// 必须通过远程区域中检索的应用程序的列表
private Map<String, Set<String>> remoteRegionAppWhitelist;
// 从远程区域取出该注册表的信息的时间间隔,默认为30秒
private int remoteRegionRegistryFetchInterval = 30;
// 用于执行远程区域注册表请求的线程池的大小,默认为20
private int remoteRegionFetchThreadPoolSize = 20;
// 用来合格请求远程区域注册表的信任存储文件,默认为空
private String remoteRegionTrustStore = "";
// 获取偏远地区信任存储文件的密码,默认为“changeit”
private String remoteRegionTrustStorePassword = "changeit";
// 如果在远程区域本地没有实例运行,对于应用程序回退的旧行为是否被禁用, 默认为false
private boolean disableTransparentFallbackToOtherRegion;
// 表示集群节点之间的复制是否为了网络效率而进行批处理,默认为false
private boolean batchReplication;
// 限流是否应启用或禁用,默认为false
private boolean rateLimiterEnabled = false;
// 是否对标准客户端进行限流,默认false
private boolean rateLimiterThrottleStandardClients = false;
// 认证的客户端列表,这里是除了标准的eureka Java客户端。
private Set<String> rateLimiterPrivilegedClients = Collections.emptySet();
// 速率限制的burst size ,默认为10,这里用的是令牌桶算法
private int rateLimiterBurstSize = 10;
// 速率限制器用的是令牌桶算法,此配置指定平均执行注册请求速率,默认为500
private int rateLimiterRegistryFetchAverageRate = 500;
// 速率限制器用的是令牌桶算法,此配置指定平均执行请求速率,默认为100
private int rateLimiterFullFetchAverageRate = 100;
// Eureka服务器是否应该登录clientAuthHeaders,默认为true
private boolean logIdentityHeaders = true;
// 用来描述从AWS第三账户的自动缩放组中的角色名称,默认为“ListAutoScalingGroups”
private String listAutoScalingGroupsRoleName = "ListAutoScalingGroups";
// 复制的数据在发送请求时是否被压缩
private boolean enableReplicatedRequestCompression = false;
// 如果没有设置默认的编解码器将使用全JSON编解码器,获取的是编码器的类名称
private String jsonCodecName;
// 如果没有设置默认的编解码器将使用xml编解码器,获取的是编码器的类名称
private String xmlCodecName;
// 服务器尝试绑定到候选Route53域的次数,默认为3
private int route53BindRebindRetries = 3;
// 服务器应该检查是否和Route53域绑定的时间间隔,默认为5 * 60 * 1000毫秒
private int route53BindingRetryIntervalMs = 5 * MINUTES;
// 用于建立route53域的ttl,默认为301
private long route53DomainTTL = 30;
// 获取配置绑定EIP或Route53的策略
private AwsBindingStrategy bindingStrategy = AwsBindingStrategy.EIP;
// 当尝试新功能迁移过程时,为了避免配置API污染,相应的配置即可投入实验配置部分
private int minAvailableInstancesForPeerReplication = -1;
private int initialCapacityOfResponseCache = 1000;
private int expectedClientRenewalIntervalSeconds = 30;
private boolean useAwsAsgApi = true;
private String myUrl;
1.2 初始化ApplicationInfoManager
ApplicationInfoManager主要用来初始化注册EurekaServer时的一些必要信息,以及提供对其他组件提供发现机制。
2. EurekaServerInitializerConfiguration 初始化
EurekaServerInitializerConfiguration类实现了ServletContextAware、SmartLifecycle、Ordered等接口,并实现了Lifecycle的start()方法,该方法主要用来初始化EurekaServer并发布一些与初始化相关的事件:
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// TODO: is this class even needed now?
// 初始化容器
EurekaServerInitializerConfiguration.this.eurekaServerBootstrap
.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
log.info("Started Eureka Server");
// 发布EurekaRegistryAvailableEvent事件
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
// 将running标识设置为true
EurekaServerInitializerConfiguration.this.running = true;
// 发布EurekaServerStartedEvent事件
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
} catch (Exception ex) {
// Help!
log.error("Could not initialize Eureka servlet context", ex);
}
}
}).start();
}
其初始化容器的代码如下:
public void contextInitialized(ServletContext context) {
try {
// 初始化Euraka环境
initEurekaEnvironment();
// 初始化EurekaServer上下文
initEurekaServerContext();
// 将上下文环境绑定到...
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
} catch (Throwable e) {
log.error("Cannot bootstrap eureka server :", e);
throw new RuntimeException("Cannot bootstrap eureka server :", e);
}
}
- 初始化Euraka环境
- 初始化EurekaServer上下文环境
- 将上下文环境绑定到
2.2 初始化Euraka环境
protected void initEurekaEnvironment() throws Exception {
log.info("Setting the eureka configuration..");
// 1、设置eureka.datacenter,如果没有配置,则将其设置为“default”
String dataCenter = ConfigurationManager.getConfigInstance().getString(EUREKA_DATACENTER);
if (dataCenter == null) {
log.info("Eureka data center value eureka.datacenter is not set, defaulting to default");
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
} else {
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
}
// 设置eureka.environment,如果没有配置,则将其设置为“test”
String environment = ConfigurationManager.getConfigInstance().getString(EUREKA_ENVIRONMENT);
if (environment == null) {
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
log.info("Eureka environment value eureka.environment is not set, defaulting to test");
} else {
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, environment);
}
}
- 设置eureka.datacenter,如果没有配置,则将其设置为“default”
- 设置eureka.environment,如果没有配置,则将其设置为“test”
2.3 初始化EurekaServer容器
protected void initEurekaServerContext() throws Exception {
// For backward compatibility
// 向后兼容
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
// Amazon aws相关(无需理会)
if (isAws(this.applicationInfoManager.getInfo())) {
this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig, this.eurekaClientConfig, this.registry, this.applicationInfoManager);
this.awsBinder.start();
}
// 将当前环境绑定到EurekaServerContextHolder
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
// Copy registry from neighboring eureka node
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
// Register all monitoring statistics.
// 注册所有监测统计数据
EurekaMonitors.registerAllStats();
}
从这段代码来看,最主要的目的是执行EurekaServerContextHolder.initialize(this.serverContext);
,这句代码会创建一个EurekaServerContextHolder对象,该对象持有了EurekaServerContext实例;但是这个EurekaServerContext是何时被创建的呢?从代码中可以看到this.serverContext是 EurekaServerBootstrap类的一个实例变量,那么我们可以推断,在EurekaServerBootstrap类初始化的时候,会先实例化其实例变量,顺着该思路再结合EurekaServer的初始化, 在EurekaServerInitializerConfiguration类中我们可以找到:
@Autowired
private EurekaServerConfig eurekaServerConfig;
private ServletContext servletContext;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private EurekaServerBootstrap eurekaServerBootstrap;
可以看到在该类中注入了EurekaServerBootstrap的实例。那么该类具体是在哪里被实例化呢?别忘了我们的分析入口EurekaServerAutoConfiguration(这时候需要连蒙带猜了,当然也是要一定依据),在该类中可以找到:
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) {
return new EurekaServerBootstrap(
this.applicationInfoManager,
this.eurekaClientConfig,
this.eurekaServerConfig,
registry,
serverContext);
}
这里对EurekaServerBootstrap进行了实例化,其有两个参数:PeerAwareInstanceRegistry和EurekaServerContext,对于@Bean注解,其参数我们可以理解为依赖bean,一定要先于EurekaServerBootstrap的实例化,继续查找:
@Bean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
return new DefaultEurekaServerContext(
this.eurekaServerConfig,
serverCodecs,
registry,
peerEurekaNodes,
this.applicationInfoManager);
}
这里又发现了ServerCodecs、PeerAwareInstanceRegistry、PeerEurekaNodes三个依赖,找到这三个依赖的实例化代码:
@Bean
public ServerCodecs serverCodecs() {
return new CloudServerCodecs(this.eurekaServerConfig);
}
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs) {
this.eurekaClient.getApplications(); // force initialization
return new InstanceRegistry(
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs, this.eurekaClient,
this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}
@Bean
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry, ServerCodecs serverCodecs) {
return new RefreshablePeerEurekaNodes(
registry,
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs,
this.applicationInfoManager);
}
从这里我们也可以看到这三者的实例化顺序为:ServerCodecs–>PeerAwareInstanceRegistry–>PeerEurekaNodes。分析了这么多,其实就是为了了解EurekaServerContext的实例化过程,在分析过程中又牵扯出来一些其他组件的实例化,下面来分析一下整个过程:为下一步的分析梳理顺序:
EurekaServerContext–>EurekaServerBootstrap–>EurekaServerContext–>PeerEurekaNodes–>PeerAwareInstanceRegistry–>ServerCodecs。当然在这过程中还牵涉到其他的组件初始化,这里我们只是捋清思路,为接下来的分析做准备。下面我们将会对这些组件及其作用一一进行分析。
2.3.1 ServerCodecs实例化
@Bean
public ServerCodecs serverCodecs() {
return new CloudServerCodecs(this.eurekaServerConfig);
}
class CloudServerCodecs extends DefaultServerCodecs {
CloudServerCodecs(EurekaServerConfig serverConfig) {
super(getFullJson(serverConfig),
CodecWrappers.getCodec(CodecWrappers.JacksonJsonMini.class),
getFullXml(serverConfig),
CodecWrappers.getCodec(CodecWrappers.JacksonXmlMini.class));
}
}
实例化话该组件的的代码很简单创建一个CloudServerCodecs对象,并接受一个EurekaServerConfig类型的参数即可(EurekaServerConfig前文已有介绍)。CloudServerCodecs继承了DefaultServerCodecs类,而官方代码中几乎没有对该类的解释说明,而且从其类名山我们也只能猜测其与编码解析之类的工作相关,下面我们只有通过分析其代码得出其作用:
protected final CodecWrapper fullJsonCodec;
protected final CodecWrapper compactJsonCodec;
protected final CodecWrapper fullXmlCodec;
protected final CodecWrapper compactXmlCodec;
protected DefaultServerCodecs(CodecWrapper fullJsonCodec,
CodecWrapper compactJsonCodec,
CodecWrapper fullXmlCodec,
CodecWrapper compactXmlCodec) {
this.fullJsonCodec = fullJsonCodec;
this.compactJsonCodec = compactJsonCodec;
this.fullXmlCodec = fullXmlCodec;
this.compactXmlCodec = compactXmlCodec;
}
从中我们可以看到该类包含了与解码相关的四个包装类并提供了全量构造函数来完成初始化,我们以其中的fullJsonCodec为例,看其初始化过程:
private static CodecWrapper getFullJson(EurekaServerConfig serverConfig) {
CodecWrapper codec = CodecWrappers.getCodec(serverConfig.getJsonCodecName());
return codec == null ? CodecWrappers.getCodec(JACKSON_JSON.codecName()) : codec;
}
结合我们之前对EurekaServerConfig中的EurekaServer配置分析,该段代码的作用是如果配置了jsonCodecName,那么则使用配置的JSON解码器,否则使用CloudJacksonJson作为JSON解码器。从CloudJacksonJson的继承关系中可以看出其主要的方法就是提供对JSON的编码和解码,从Eureka的官方测试类中我们可以看到对于InstanceInfo实力对象Eureka已经提供了很好的JSON编码和解码能力,当然实际应用中我们也可以扩展自定义实现。对于其他三个参数的分析应该是大同小异,不再赘述。
@Test
public void customCodecWorks() throws Exception {
assertThat(this.serverCodecs).as("serverCodecs is wrong type")
.isInstanceOf(EurekaServerAutoConfiguration.CloudServerCodecs.class);
CodecWrapper codec = this.serverCodecs.getFullJsonCodec();
assertThat(codec).as("codec is wrong type").isInstanceOf(CloudJacksonJson.class);
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder().setAppName("fooapp")
.add("instanceId", "foo").build();
String encoded = codec.encode(instanceInfo);
InstanceInfo decoded = codec.decode(encoded, InstanceInfo.class);
assertThat(decoded.getInstanceId()).as("instanceId was wrong").isEqualTo("foo");
}
2.3.2 PeerAwareInstanceRegistry实例化
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs) {
this.eurekaClient.getApplications(); // force initialization
return new InstanceRegistry(
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs, this.eurekaClient,
this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}
2.3.3 实例化PeerEurekaNodes
@Bean
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry, ServerCodecs serverCodecs) {
return new RefreshablePeerEurekaNodes(
registry,
this.eurekaServerConfig,
this.eurekaClientConfig,
serverCodecs,
this.applicationInfoManager);
}
PeerEurekaNode是一个工具类,其提供了对注册到Euraka服务器的生命周期管理,如Register、Renew、Cancel、Expiration等。RefreshablePeerEurekaNodes是其子类,其重写了onApplicationEvent方法并提供了一个shouldUpdate方法(检查特定属性是否已更改),其更新的条件如下:
- eureka.client.use-dns-for-fetching-service-urls(eureka客户端是否应该使用DNS机制来获取eureka服务器的地址列表,默认为false) 为false
- eureka.client.availability-zones(获取实例所在的地区下可用性的区域列表,用逗号隔开)
- eureka.client.region(获取实例所在的地区。默认为us-east-1)
- eureka.client.service-url(Eureka服务器的链接)
2.3.4 EurekaServerContext实例化
@Bean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
return new DefaultEurekaServerContext(
this.eurekaServerConfig,
serverCodecs,
registry,
peerEurekaNodes,
this.applicationInfoManager);
}
@Inject
public DefaultEurekaServerContext(EurekaServerConfig serverConfig,
ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry,
PeerEurekaNodes peerEurekaNodes,
ApplicationInfoManager applicationInfoManager) {
this.serverConfig = serverConfig;
this.serverCodecs = serverCodecs;
this.registry = registry;
this.peerEurekaNodes = peerEurekaNodes;
this.applicationInfoManager = applicationInfoManager;
}
该类实例化比较简单,不在赘述。
2.3.5 EurekaServerBootstrap实例化
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) {
return new EurekaServerBootstrap(
this.applicationInfoManager,
this.eurekaClientConfig,
this.eurekaServerConfig,
registry,
serverContext);
}
public EurekaServerBootstrap(ApplicationInfoManager applicationInfoManager,
EurekaClientConfig eurekaClientConfig,
EurekaServerConfig eurekaServerConfig,
PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
this.applicationInfoManager = applicationInfoManager;
this.eurekaClientConfig = eurekaClientConfig;
this.eurekaServerConfig = eurekaServerConfig;
this.registry = registry;
this.serverContext = serverContext;
}
该类实例化比较简单,不在赘述。