启动过程
众所周知,springboot应用启动的时候会加载classPath下jar包中spring.factories文件,而sringcloud正是充分利用了这一自动装配的特点,加载了eureka-server的EurekaServerAutoConfiguration配置类
直接进入配置类,首先看注解@ConditionalOnBean({Marker.class}),当Marker实例对象存在的时候该配置类才生效,也就是说需要有个maker bean才能装配到eureka-server,而这个marker由@EnableEurekaServer注解中组合注解决定,一个巧妙的开关注解就这样完成了。
再回到EurekaServerAutoConfiguration中,注入很多Bean,我们先看EurekaServerContext,注入了一个DefaultEurekaServerContext上下文,进入后会看到一个initialize()初始化方法被@PostConstruct所注解,也就是说在DefaultEurekaServerContext构建完后会执行这个方法。该方法中可以看到PeerAwareInstanceRegistry,PeerEurekaNodes的启动项。这两个Bean在主配置类中已经注入,进入this.peerEurekaNodes.start()。
可见该方法开启了线程池去更新什么东西,PeerEurekaNodes.this.resolvePeerUrls()该方法返回的是一个list集合,可以发现通过EurekaClient(用来给eureka-server注册实例的接口)获取可用的server-url,并且通过isThisMyUrl过滤了自身的url,然后进入updatePeerEurekaNodes。
protected void updatePeerEurekaNodes(List<String> newPeerUrls) {
if (newPeerUrls.isEmpty()) {
//如果url为空就不更新
logger.warn("The replica size seems to be empty. Check the route 53 DNS Registry");
} else {
Set<String> toShutdown = new HashSet(this.peerEurekaNodeUrls);
toShutdown.removeAll(newPeerUrls);
Set<String> toAdd = new HashSet(newPeerUrls);
toAdd.removeAll(this.peerEurekaNodeUrls);
if (!toShutdown.isEmpty() || !toAdd.isEmpty()) {
List<PeerEurekaNode> newNodeList = new ArrayList(this.peerEurekaNodes);
//移除不可用的节点
if (!toShutdown.isEmpty()) {
logger.info("Removing no longer available peer nodes {}", toShutdown);
int i = 0;
while(i < newNodeList.size()) {
PeerEurekaNode eurekaNode = (PeerEurekaNode)newNodeList.get(i);
if (toShutdown.contains(eurekaNode.getServiceUrl())) {
newNodeList.remove(i);
eurekaNode.shutDown();
} else {
++i;
}
}
}
//通过http添加新的节点信息
if (!toAdd.isEmpty()) {
logger.info("Adding new peer nodes {}", toAdd);
Iterator var7 = toAdd.iterator();
while(var7.hasNext()) {
String peerUrl = (String)var7.next();
newNodeList.add(this.createPeerEurekaNode(peerUrl));
}
}
//节点与URL集合更新
this.peerEurekaNodes = newNodeList;
this.peerEurekaNodeUrls = new HashSet(newPeerUrls);
}
}
}
由此可知updatePeerEurekaNodes是用来更新集群节点信息的,主配置类所注入的PeerEurekaNode等同于对等节点信息封装操作的Bean,PeerEurekaNode的子类RefreshablePeerEurekaNodes监听了环境变化动态更新节点信息同样注入主配置类中。
回到context中,往下this.registry.init(this.peerEurekaNodes),关于server端的一些初始化操作,比如ResponseCacheImpl的缓存初始化,这边先跳过。
回到主配置类中,再看注解@Import({EurekaServerInitializerConfiguration.class}),EurekaServerInitializerConfiguration中实现了SmartLifecycle,SmartLifecycle是spring容器的bean创建完成后执行start方法做一些事情,重点关注start中的this.eurekaServerBootstrap.contextInitialized(this.servletContext),初始化了EurekaServerContext的细节,跟进initEurekaServerContext这个方法:
protected void initEurekaServerContext() throws Exception {
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), 10000);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), 10000);
if (this.isAws(this.applicationInfoManager.getInfo())) {
this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig, this.eurekaClientConfig, this.registry, this.applicationInfoManager);
this.awsBinder.start();
}
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
**//
从集群中的server同步注册信息
**
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
EurekaMonitors.registerAllStats();
}
public int syncUp() {
int count = 0;
//重试
for(int i = 0; i < this.serverConfig.getRegistrySyncRetries() && count == 0; ++i) {
if (i > 0) {
try {
Thread.sleep(this.serverConfig.getRegistrySyncRetryWaitMs());
} catch (InterruptedException var10) {
logger.warn("Interrupted during registry transfer..");
break;
}
}
//远程注册表信息
Applications apps = this.eurekaClient.getApplications();
Iterator var4 = apps.getRegisteredApplications().iterator();
while(var4.hasNext()) {
Application app = (Application)var4.next();
Iterator var6 = app.getInstances().iterator();
while(var6.hasNext()) {
InstanceInfo instance = (InstanceInfo)var6.next();
try {
if (this.isRegisterable(instance)) {
***//
同步到自己的内存中
//***
this.register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
++count;
}
} catch (Throwable var9) {
logger.error("During DS init copy", var9);
}
}
}
}
return count;
}
由此得知PeerAwareInstanceRegistry,是一个感知对等节点的注册器,对于新server加入集群,服务注册,服务心跳以及剔除自我保护时候的影响的感知。
总结:
1)通过marker控制配置类加载
2)context去启动更新eureka对等节点信息
3)初始化了EurekaServerContext的细节去感知新server加入集群,服务注册,服务心跳以及剔除自我保护时候的影响的感知