Spring Cloud 2.2.2 源碼之五十五nacos服務端處理註冊實例請求三

Service模型大致結構

在這裏插入圖片描述

ServiceManager的addIpAddresses

上篇說到增加實例這裏,看看他是怎麼添加的:
在這裏插入圖片描述

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

實例創建好了,返回了新的實例集合,這個時候就去放到一致性服務裏了:
在這裏插入圖片描述
會根據傳進來的是臨時的還是永久的key來選擇對應的服務。
在這裏插入圖片描述

下篇繼續將對應的服務怎麼處理實例集合。

好了,今天就到這裏了,希望對學習理解有幫助,大神看見勿噴,僅爲自己的學習理解,能力有限,請多包涵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章