我是靠谱客的博主 糊涂缘分,最近开发中收集的这篇文章主要介绍eureka之服务器注册表与本地注册表不一致检查的源码Bug,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.源码定位

方法:com.netflix.discovery.shared.Applications#getReconcileMapDiff

作用: 检查本地缓存的注册表和eureka 服务器注册表不一致的地方

版本: 1.7.x

github: https://github.com/Netflix/eureka/tree/v1.7.x


2.源码简单解析

public Map<String, List<String>> getReconcileMapDiff(Applications apps) {
        // 本地注册表与服务器注册表区别存储
        Map<String, List<String>> diffMap = new TreeMap<String, List<String>>();
        // 本地注册表的服务名和服务实例ID 双元素集合
        Set<Pair> allInstanceAppInstanceIds = new HashSet<Pair>();
        for (Application otherApp : apps.getRegisteredApplications()) {
            // 本地服务信息
            Application thisApp = this.getRegisteredApplications(otherApp.getName());
            if (thisApp == null) {
                logger.warn("Application not found in local cache : {}", otherApp.getName());
                continue;
            }
            for (InstanceInfo instanceInfo : thisApp.getInstancesAsIsFromEureka()) {
                // 本地缓存注册表的的服务名与服务实例键值对
                allInstanceAppInstanceIds.add(new Pair(thisApp.getName(),
                        instanceInfo.getId()));
            }
            for (InstanceInfo otherInstanceInfo : otherApp.getInstancesAsIsFromEureka()) {
                // 本地缓存注册表中是否包含指定实例id
                InstanceInfo thisInstanceInfo = thisApp.getByInstanceId(otherInstanceInfo.getId());
                if (thisInstanceInfo == null) {
                    // 本地缓存里没有这个实例id,则标记为被删除状态
                    List<String> diffList = diffMap.get(ActionType.DELETED.name());
                    if (diffList == null) {
                        diffList = new ArrayList<String>();
                        diffMap.put(ActionType.DELETED.name(), diffList);
                    }
                    // 加到注册表区别map集合的删除状态List集合中
                    // 就是eureka server有,本地没有的服务实例
                    diffList.add(otherInstanceInfo.getId());
                } else if (!thisInstanceInfo.getStatus().name()
                        .equalsIgnoreCase(otherInstanceInfo.getStatus().name())) {
                    // 这里是eureka server 和 本地缓存的注册表不同时,需要记录的
                    List<String> diffList = diffMap.get(ActionType.MODIFIED.name());
                    if (diffList == null) {
                        diffList = new ArrayList<String>();
                        diffMap.put(ActionType.MODIFIED.name(), diffList);
                    }
                    // 记录信息为: 服务实例id_本地缓存服务实例状态_服务器服务实例状态
                    diffList.add(thisInstanceInfo.getId()
                            + APP_INSTANCEID_DELIMITER
                            + thisInstanceInfo.getStatus().name()
                            + APP_INSTANCEID_DELIMITER
                            + otherInstanceInfo.getStatus().name());
                }
                // 服务器和本地都有的进行删除
                allInstanceAppInstanceIds.remove(new Pair(otherApp.getName(), otherInstanceInfo.getId()));
            }
        }
        for (Pair pair : allInstanceAppInstanceIds) {
            // 这里剩下的都是本地有,服务器没有的
            Application app = new Application(pair.getItem1());
            /**
             * public Application(String name) {
             *  this.name = StringCache.intern(name);
             *  instancesMap = new ConcurrentHashMap<String, InstanceInfo>();
             *  instances = new LinkedHashSet<InstanceInfo>();
             *}
             */
            // 这里能拿到东西??????? 迷~
            InstanceInfo thisInstanceInfo = app.getByInstanceId(pair.getItem2());
            if (thisInstanceInfo != null) {
                List<String> diffList = diffMap.get(ActionType.ADDED.name());
                if (diffList == null) {
                    diffList = new ArrayList<String>();
                    diffMap.put(ActionType.ADDED.name(), diffList);
                }
                diffList.add(thisInstanceInfo.getId());
            }
        }
        return diffMap;

    }

上面主要做了个啥呢?简单总结一下:

  1. diffMap 存储的就是本地注册表和服务器注册表不一致的地方
  2. diffMap的存储key有三种DELETED,MODIFIED,ADDED
    1. DELETED 标识服务器有该注册实例,而本地没有
    2. MODIFIED标识服务和本地注册表都有该服务实例,但是状态不一致
    3. ADDED 标识本地有,而服务器没有
  3. 拿着本地和服务器的注册表进行比对,将服务实例ID根据判断条件分别仿佛以上三种状态的List集合中

问题就出现在ADDED状态中

for (Pair pair : allInstanceAppInstanceIds) {
    // 这里剩下的都是本地有,服务器没有的
    Application app = new Application(pair.getItem1());
    /**
     * public Application(String name) {
     *  this.name = StringCache.intern(name);
     *  instancesMap = new ConcurrentHashMap<String, InstanceInfo>();
     *  instances = new LinkedHashSet<InstanceInfo>();
     *}
     */
    // 这里能拿到东西??????? 迷~
    InstanceInfo thisInstanceInfo = app.getByInstanceId(pair.getItem2());
    if (thisInstanceInfo != null) {
        List<String> diffList = diffMap.get(ActionType.ADDED.name());
        if (diffList == null) {
            diffList = new ArrayList<String>();
            diffMap.put(ActionType.ADDED.name(), diffList);
        }
        diffList.add(thisInstanceInfo.getId());
    }
}

上面这段代码本意我认为应该是找出了本地有而服务器没有的实例ID,但是在获取app这个对象时,有点小bug,这里应该是从本地注册表中获取,而不是自己去new出来一个Application对象,这是个空对象。下面获取的thisInstanceInfo 将永远为null。

在官网的master分支上,这里关于记录本地注册表和服务器注册表不同之处的功能已经被干掉了~ 所以可以不用care~

最后

以上就是糊涂缘分为你收集整理的eureka之服务器注册表与本地注册表不一致检查的源码Bug的全部内容,希望文章能够帮你解决eureka之服务器注册表与本地注册表不一致检查的源码Bug所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部