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~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值