SpringCloud-Eureka服务端集群如何同步(5)

一.起源

1.前景回顾

SpringCloud-Eureka服务端启动过程源码分析(4)

在上一篇中,我们解析了Eureka服务端启动过程。其中第五点涉及到服务器端集群同步问题我们并没有进行深入了解,在这里,我们将进行一次探索。

// 获取集群中的其他节点,注册到当前节点上
int registryCount = this.registry.syncUp();

二.集群同步

1.为什么要进行集群同步

首先,我们需要知道Eureka为什么要集群?Eureka使用集群的目的是为了实现负载均衡+高可用。

作为微服务的解耦核心,如果只有一台,那么GG后,整个微服务都将无法使用。

为了保证高可用,eureka通过部署多台机器,且相互注册,互为副本,并作为一个整体对外暴露,当其中任意多台机器挂掉,只要还有存活的机器,那么整个集群就仍然能对外提供服务。

同时,Eureka集群会将集群中所有机器对外暴露,所以,服务提供者和服务消费者可以选取任意机器进行连接,实现了分流,降低单台eureka服务器的压力。

这里有个疑惑点,服务提供者和服务消费者在获得整个集群列表是如何选择连接哪一台呢?留待后续解析客户端后再进行解答

2.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;
    

在上面源代码分析中,我们可以得出以下两点结论

  1. syncUp不是自己直接去兄弟节点拿信息,而是在等着谁在拿来放在localRegionApps
  2. 只要同步一个兄弟节点信息后,就会放行,多次同步失败后,也会放行。

3.谁是幕后黑手?

那到底是谁把数据放到localRegionApps中的呢?

通过查看被引用位置,我们可以看到,总共有四处进行了set设置,由于数量较少,那我们都看看

在哪设置了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BwKJ6qcl-1605626516677)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2a6a7e6f-1fd4-440f-a5fe-c67beef242f4/Untitled.png)]

1.第一个在DiscoveryClient的构造方法上,new 了一个空的Applications,我想这应该并不是我们想要的,毕竟兄弟节点的信息来的不可能这么粗糙

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sH4tsV5Q-1605626516680)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/89eb36af-c40e-4948-9e08-975a2ce5b1d5/Untitled.png)]

2.第二个在com.netflix.discovery.DiscoveryClient#getAndStoreFullRegistry 下,我们可以看到,无论是注释,还是日志,还是文件名都告诉我们呢,这是在从eureka server(eureka服务器)拉取全部的注册信息,并存储到本地。(没错就是这个)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3VJHwvi-1605626516681)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/ee7707e9-db25-4e22-99fe-f1a4a65d1fae/Untitled.png)]

3.第三个在com.netflix.discovery.DiscoveryClient#reconcileAndLogDifference这个可能看起来也有点像,毕竟也是在从eureka服务端拉去注册信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZLoLwLS-1605626516682)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/bcff8655-3886-4e72-8032-38784ed1ad0b/Untitled.png)]

然而并不是,我们可以观察一下这个方法的后续调用:

1.在com.netflix.discovery.DiscoveryClient#getAndUpdateDelta 方法里调用的了reconcileAndLogDifference

2.在com.netflix.discovery.DiscoveryClient#fetchRegistry方法李调用了getAndUpdateDelta

3.研究fetchRegistry 我们发现,兜兜转转又回到了第二点**getAndStoreFullRegistry** 方法上,在这里我们可以看到,getAndUpdateDelta方法是进行更新的,所以再次确认第二点的结论是正确的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mbkFL3lC-1605626516683)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/57c5c701-d6cc-4a99-8403-cf67647a0b90/Untitled.png)]

4.com.netflix.discovery.DiscoveryClient#fetchRegistryFromBackup 这个方法的作用是当集群中所有其他服务器都无法连接时,将从备份中获取所有注册信息。这其实是一个很典型的分区容错,看到底是保证AP还是CP。这里我们呢可以看到,这里保证了AP,也就是高可用性,无法保证各个节点的数据一致性。(CAP理论后续有空再聊

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EkmZhUAn-1605626516684)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6d00ddc1-8ce5-4b96-a742-6f2e22dfbf4f/Untitled.png)]

三.结论

1.基本结论

服务端通过syncUp 等待localRegionApps 中有其他节点注册信息后进行同步,而localRegionApps**com.netflix.discovery.DiscoveryClient#getAndStoreFullRegistry** 进行了Eureka服务器节点获取并设置到localRegionApps 中,而此时,服务器便可以将Eureka服务器节点中的信息同步到自身的注册表中。达到集群同步的效果。

2.不足

这里只是粗略的讲解了一下当前节点上线时,已有集群服务器节点启动的情况。针对未有集群节点启动,当前服务启动后,再启动集群其他服务节点如何同步问题,我们将在后面进行讲解。
由于工作和自身的惰性,这篇文章差不多延迟了将近一个星期。我希望我能坚持记录自己的学习心得,与诸君共勉~

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值