赞
踩
SpringCloud-Eureka服务端启动过程源码分析(4)
在上一篇中,我们解析了Eureka服务端启动过程。其中第五点涉及到服务器端集群同步问题我们并没有进行深入了解,在这里,我们将进行一次探索。
// 获取集群中的其他节点,注册到当前节点上
int registryCount = this.registry.syncUp();
首先,我们需要知道Eureka为什么要集群?Eureka使用集群的目的是为了实现负载均衡+高可用。
作为微服务的解耦核心,如果只有一台,那么GG后,整个微服务都将无法使用。
为了保证高可用,eureka通过部署多台机器,且相互注册,互为副本,并作为一个整体对外暴露,当其中任意多台机器挂掉,只要还有存活的机器,那么整个集群就仍然能对外提供服务。
同时,Eureka集群会将集群中所有机器对外暴露,所以,服务提供者和服务消费者可以选取任意机器进行连接,实现了分流,降低单台eureka服务器的压力。
这里有个疑惑点,服务提供者和服务消费者在获得整个集群列表是如何选择连接哪一台呢?留待后续解析客户端后再进行解答。
从上一篇中,我们可以看到,在syncUp
方法后才会标识自己已经UP
,而在UP
之前是要在syncUp
这个点至多阻塞(serverConfig.getRegistrySyncRetries
* serverConfig.getRegistrySyncRetryWaitMs()
) 毫秒。阻塞在这里是为了干什么呢?就是在等待从集群中其他服务器节点那里获取注册信息并同步到自身注册表中。
@Override public int syncUp() { // 从集群中其他节点获取注册信息 // 注册数 int count = 0; // 会进行多次尝试去注册节点信息到自己的注册表中 for (int i = 0; ((i < serverConfig.getRegistrySyncRetries()) && (count == 0)); i++) { if (i > 0) { try { // 当第一没有拿到其他服务器节点信息时,会先睡会儿等待服务器先去拿 // 那么在这个sleep的过程中,是谁在做这个拿的事情呢? Thread.sleep(serverConfig.getRegistrySyncRetryWaitMs()); } catch (InterruptedException e) { logger.warn("Interrupted during registry transfer.."); break; } } //从本地com.netflix.discovery.DiscoveryClient#localRegionApps 本地变量中获取 Applications apps = eurekaClient.getApplications(); for (Application app : apps.getRegisteredApplications()) { for (InstanceInfo instance : app.getInstances()) { try { if (isRegisterable(instance)) { //注册到com.netflix.eureka.registry.AbstractInstanceRegistry#registry中 register(instance, instance.getLeaseInfo().getDurationInSecs(), true); count++; } } catch (Throwable t) { logger.error("During DS init copy", t); } } } } return count;
在上面源代码分析中,我们可以得出以下两点结论
localRegionApps
中那到底是谁把数据放到localRegionApps
中的呢?
通过查看被引用位置,我们可以看到,总共有四处进行了set
设置,由于数量较少,那我们都看看
在哪设置了。
1.第一个在DiscoveryClient的构造方法上,new 了一个空的Applications,我想这应该并不是我们想要的,毕竟兄弟节点的信息来的不可能这么粗糙
2.第二个在com.netflix.discovery.DiscoveryClient#getAndStoreFullRegistry
下,我们可以看到,无论是注释,还是日志,还是文件名都告诉我们呢,这是在从eureka server(eureka服务器)拉取全部的注册信息,并存储到本地。(没错就是这个)
3.第三个在com.netflix.discovery.DiscoveryClient#reconcileAndLogDifference
下,这个可能看起来也有点像,毕竟也是在从eureka服务端拉去注册信息。
然而并不是,我们可以观察一下这个方法的后续调用:
1.在com.netflix.discovery.DiscoveryClient#getAndUpdateDelta
方法里调用的了reconcileAndLogDifference
2.在com.netflix.discovery.DiscoveryClient#fetchRegistry
方法李调用了getAndUpdateDelta
3.研究fetchRegistry
我们发现,兜兜转转又回到了第二点**getAndStoreFullRegistry
** 方法上,在这里我们可以看到,getAndUpdateDelta
方法是进行更新的,所以再次确认第二点的结论是正确的。
4.com.netflix.discovery.DiscoveryClient#fetchRegistryFromBackup
这个方法的作用是当集群中所有其他服务器都无法连接时,将从备份中获取所有注册信息。这其实是一个很典型的分区容错,看到底是保证AP还是CP。这里我们呢可以看到,这里保证了AP,也就是高可用性,无法保证各个节点的数据一致性。(CAP理论后续有空再聊。)
服务端通过syncUp
等待localRegionApps
中有其他节点注册信息后进行同步,而localRegionApps
在 **com.netflix.discovery.DiscoveryClient#getAndStoreFullRegistry
** 进行了Eureka服务器节点获取并设置到localRegionApps
中,而此时,服务器便可以将Eureka服务器节点中的信息同步到自身的注册表中。达到集群同步的效果。
这里只是粗略的讲解了一下当前节点上线时,已有集群服务器节点启动的情况。针对未有集群节点启动,当前服务启动后,再启动集群其他服务节点如何同步问题,我们将在后面进行讲解。
由于工作和自身的惰性,这篇文章差不多延迟了将近一个星期。我希望我能坚持记录自己的学习心得,与诸君共勉~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。