三、Eureka源码解析:客户端服务列表的获取与更新

本文详细解析了Eureka客户端如何从注册中心获取并更新服务列表,包括增量更新的机制、更新频率、一致性哈希码的使用以及全量更新的触发条件。Eureka客户端每30秒进行一次增量更新,获取Eureka server最近三分钟的变更,通过一致性哈希码确保数据一致性。当数据不一致时,会触发全量更新。此外,介绍了Eureka客户端和服务端的交互过程,如网络请求、数据合并及缓存策略。
摘要由CSDN通过智能技术生成

1、Eureka client从注册中心更新服务列表,然后自身会做缓存;

2、作为服务消费者,就是从这些缓存信息中获取的服务提供者的信息;

3、增量更新的服务以30秒为周期循环调用;

4、增量更新数据在服务端保存时间为3分钟,因此Eureka client取得的数据虽然被称为"增量更新",仍然可能和30秒前取的数据一样,所以Eureka client要自己来处理重复信息;

5、由3、4两点可以推断出,Eureka client的增量更新,其实获取的是Eureka server最近三分钟内的变更,因此,如果Eureka client有超过三分钟没有做增量更新的话(例如网络问题),那么再调用增量更新接口时,那三分钟内Eureka server的变更就可能获取不到了,这就造成了Eureka server和Eureka client之间的数据不一致,需要有个方案来及时发现这个问题;

6、正常情况下,Eureka client多次增量更新后,最终的服务列表数据应该Eureka server保持一致,但如果期间发生异常,可能导致和Eureka server的数据不一致,为了暴露这个问题,Eureka server每次返回的增量更新数据中,会带有一致性哈希码,Eureka client用本地服务列表数据算出的一致性哈希码应该和Eureka server返回的一致,若不一致就证明增量更新出了问题导致Eureka client和Eureka server上的服务列表信息不一致了,此时需要全量更新;

7、Eureka server上的服务列表信息对外提供JSON/XML两种格式下载;

8、Eureka client使用jersey的SDK,去下载JSON格式的服务列表信息;

服务列表获取更新:

注释消息: 这可以确保对要获取的远程区域进行动态更改。

 注释消息: 这两块区域都需要进行同步

注释消息:  只刷新映射以反映任何DNS/属性更改

 

 

更新服务列表,根据入参判断进行全量更新还是增量更新

private boolean fetchRegistry(boolean forceFullRegistryFetch) {

        //用Stopwatch做耗时分析

        Stopwatch tracer = FETCH_REGISTRY_TIMER.start();

 

        try {

            // 取出本地缓存的,之气获取的服务列表信息

            Applications applications = getApplications();

 

            //判断多个条件,确定是否触发全量更新,如下任一个满足都会全量更新:

            //1. 是否禁用增量更新;

            //2. 是否对某个region特别关注;

            //3. 外部调用时是否通过入参指定全量更新;

            //4. 本地还未缓存有效的服务列表信息;

            if (clientConfig.shouldDisableDelta()

                    || (!Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress()))

                    || forceFullRegistryFetch

                    || (applications == null)

                    || (applications.getRegisteredApplications().size() == 0)

                    || (applications.getVersion() == -1)) //Client application does not have latest library supporting delta

            {

                //这些详细的日志可以看出触发全量更新的原因

                logger.info("Disable delta property : {}", clientConfig.shouldDisableDelta());

                logger.info("Single vip registry refresh property : {}", clientConfig.getRegistryRefreshSingleVipAddress());

                logger.info("Force full registry fetch : {}", forceFullRegistryFetch);

                logger.info("Application is null : {}", (applications == null));

                logger.info("Registered Applications size is zero : {}",

                        (applications.getRegisteredApplications().size() == 0));

                logger.info("Application version is -1: {}", (applications.getVersion() == -1));

                //全量更新

                getAndStoreFullRegistry();

            } else {

                //增量更新

                getAndUpdateDelta(applications);

            }

            //重新计算和设置一致性hash码

            applications.setAppsHashCode(applications.getReconcileHashCode());

            //日志打印所有应用的所有实例数之和

            logTotalInstances();

        } catch (Throwable e) {

            logger.error(PREFIX + appPathIdentifier + " - was unable to refresh its cache! status = " + e.getMessage(), e);

            return false;

        } finally {

            if (tracer != null) {

                tracer.stop();

            }

        }

 

        //将本地缓存更新的事件广播给所有已注册的监听器,注意该方法已被CloudEurekaClient类重写

        onCacheRefreshed();

 

        //检查刚刚更新的缓存中,有来自Eureka server的服务列表,其中包含了当前应用的状态,

        //当前实例的成员变量lastRemoteInstanceStatus,记录的是最后一次更新的当前应用状态,

        //上述两种状态在updateInstanceRemoteStatus方法中作比较 ,如果不一致,就更新lastRemoteInstanceStatus,并且广播对应的事件

        updateInstanceRemoteStatus();

 

        return true;

    }

全量更新:

private void getAndStoreFullRegistry() throws Throwable {

        long currentUpdateGeneration = fetchRegistryGeneration.get();

 

        logger.info("Getting all insta

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值