2023-09-15
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105834317

Service模型大致结构

202309152318259571.png

ServiceManager的addIpAddresses

上篇说到增加实例这里,看看他是怎么添加的:

202309152318265272.png

ServiceManager的addIpAddresses

做的是一个添加的操作。

    public static final String UPDATE_INSTANCE_ACTION_ADD = "add";
    
        public List<Instance> addIpAddresses(Service service, boolean ephemeral, Instance... ips) throws NacosException {
            return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD, ephemeral, ips);
        }

updateIpAddresses更新服务实例

这里面还做了挺多的事,先是获取老的数据(持久的或者临时的),从一致性服务里获取,因为这个数据是要同步更新的,所以要拿出来及时更新,然后获取服务实例(持久的或者临时的),用他们来更新的老的数据,然后遍历新增的实例,如果没有集群的话先创建集群,并初始化集群,会开启心跳检查,最后根据是添加还是删除实例来更新老的实例映射,最后封装成集合返回最新的实例集合。

        public List<Instance> updateIpAddresses(Service service, String action, boolean ephemeral, Instance... ips) throws NacosException {
            //获取老的实例集合数据
            Datum datum = consistencyService.get(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), ephemeral));
            //获取集群中所有相关的实例集合,临时的或者是永久的
            List<Instance> currentIPs = service.allIPs(ephemeral);
            Map<String, Instance> currentInstances = new HashMap<>(currentIPs.size());//IP端口和实例的映射
            Set<String> currentInstanceIds = Sets.newHashSet();//实例ID集合
            //放入对应的集合里
            for (Instance instance : currentIPs) {
                currentInstances.put(instance.toIPAddr(), instance);
                currentInstanceIds.add(instance.getInstanceId());
            }
            //更新后的老的实例集合
            Map<String, Instance> instanceMap;
            if (datum != null) {//根据当前服务实例的健康标志和心跳时间,来更新老的实例集合数据
                instanceMap = setValid(((Instances) datum.value).getInstanceList(), currentInstances);
            } else {//重新创建一个
                instanceMap = new HashMap<>(ips.length);
            }
    
            for (Instance instance : ips) {//遍历新的实例
                if (!service.getClusterMap().containsKey(instance.getClusterName())) {//不存在就创建服务实例集群
                    Cluster cluster = new Cluster(instance.getClusterName(), service);
                    cluster.init();//初始化,开启集群心跳检查
                    service.getClusterMap().put(instance.getClusterName(), cluster);//添加服务实例集群
                    Loggers.SRV_LOG.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
                        instance.getClusterName(), instance.toJSON());
                }
                //删除操作的话就删除老的实例集合的数据
                if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
                    instanceMap.remove(instance.getDatumKey());
                } else {//否则添加
                    instance.setInstanceId(instance.generateInstanceId(currentInstanceIds));
                    instanceMap.put(instance.getDatumKey(), instance);
                }
    
            }
    
            if (instanceMap.size() <= 0 && UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD.equals(action)) {
                throw new IllegalArgumentException("ip list can not be empty, service: " + service.getName() + ", ip list: "
                    + JSON.toJSONString(instanceMap.values()));
            }
            //返回总的实例集合
            return new ArrayList<>(instanceMap.values());
        }

Service的allIPs获取集群中的实例集合

遍历集群,获取集群里的实例集合,临时的或者是永久的。

        public List<Instance> allIPs(boolean ephemeral) {
            List<Instance> allIPs = new ArrayList<>();
            for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
                allIPs.addAll(entry.getValue().allIPs(ephemeral));
            }
    
            return allIPs;
        }

ServiceManager的setValid更新老的实例集合

其实就是用服务集群中获取的实例集合去更新老的实例集合,健康状态和心跳时间。

        private Map<String, Instance> setValid(List<Instance> oldInstances, Map<String, Instance> map) {
    
            Map<String, Instance> instanceMap = new HashMap<>(oldInstances.size());
            for (Instance instance : oldInstances) {//遍历老的实例集合,如果新的实例存在的话就更新
                Instance instance1 = map.get(instance.toIPAddr());//获取对应新的实例
                if (instance1 != null) {//存在就更新
                    instance.setHealthy(instance1.isHealthy());
                    instance.setLastBeat(instance1.getLastBeat());
                }
                instanceMap.put(instance.getDatumKey(), instance);//放入映射
            }
            return instanceMap;
        }

Cluster的init集群初始化

即是开启一个心跳检查的任务,具体任务后面说。

        public void init() {
            if (inited) {
                return;
            }
            checkTask = new HealthCheckTask(this);
    
            HealthCheckReactor.scheduleCheck(checkTask);
            inited = true;
        }

DelegateConsistencyServiceImpl的put

实例创建好了,返回了新的实例集合,这个时候就去放到一致性服务里了:

202309152318273083.png
会根据传进来的是临时的还是永久的key来选择对应的服务。

202309152318279994.png

下篇继续将对应的服务怎么处理实例集合。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文