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

客戶端註冊實例流程

在這裏插入圖片描述

ServiceManager的putServiceAndInit

繼續上一篇,開始進來的時候服務爲空,於是創建一個Service,設置好屬性,然後進行初始化並放入映射和監聽器裏。我們先將臨時的服務情況,也就是關閉了就沒了。臨時的服務實例key可能是這樣com.alibaba.nacos.naming.iplist.ephemeral.public##DEFAULT_GROUP@@cloud-alibaba-provider-payment,永久的是com.alibaba.nacos.naming.iplist.public##DEFAULT_GROUP@@cloud-alibaba-provider-payment,其實就是臨時的在public前多了ephemeral

    private void putServiceAndInit(Service service) throws NacosException {
        putService(service);//添加到命名空間中
        service.init();//心跳初始化
        //生成key放入一致性服務裏,永久的和臨時的
        consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
        consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
        Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
    }

ServiceManager的putService

放進命名空間映射中。

    public void putService(Service service) {
        if (!serviceMap.containsKey(service.getNamespaceId())) {//如果還沒有命名空間就增加命名一個空間
            synchronized (putServiceLock) {
                if (!serviceMap.containsKey(service.getNamespaceId())) {
                    serviceMap.put(service.getNamespaceId(), new ConcurrentHashMap<>(16));
                }
            }
        }
        serviceMap.get(service.getNamespaceId()).put(service.getName(), service);//放到命名空間裏
    }

Service的init初始化和開啓心跳檢測

服務初始化,開啓一個心跳檢測,檢測所有的服務實例是否還在,延遲5秒,間隔5秒一次。

private ClientBeatCheckTask clientBeatCheckTask = new ClientBeatCheckTask(this);


    public void init() {
        //心跳檢查,延遲5秒,間隔5秒
        HealthCheckReactor.scheduleCheck(clientBeatCheckTask);

        for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
            entry.getValue().setService(this);
            entry.getValue().init();
        }
    }

HealthCheckReactor的scheduleCheck

開啓一個延遲5秒,間隔5秒的心跳任務,具體幹什麼的後面說,然後結果放進futureMap中,後續可以取消操作。

private static Map<String, ScheduledFuture> futureMap = new ConcurrentHashMap<>();


    public static void scheduleCheck(ClientBeatCheckTask task) {
        futureMap.putIfAbsent(task.taskKey(), EXECUTOR.scheduleWithFixedDelay(task, 5000, 5000, TimeUnit.MILLISECONDS));
    }

DelegateConsistencyServiceImpl的listen

代理了臨時和永久兩個服務,如果是特殊的com.alibaba.nacos.naming.domains.meta.就直接註冊到永久一致性服務和臨時一致性服務裏。否則的話就看是臨時的服務還是永久的,選一個註冊進去。

    @Override
    public void listen(String key, RecordListener listener) throws NacosException {

        // this special key is listened by both:
        if (KeyBuilder.SERVICE_META_KEY_PREFIX.equals(key)) {//特殊前綴key兩個都監聽
            persistentConsistencyService.listen(key, listener);
            ephemeralConsistencyService.listen(key, listener);
            return;
        }

        mapConsistencyService(key).listen(key, listener);//添加監聽器,添加到臨時或者永久的一致性服務的監聽器中
    }

二選一:

    private ConsistencyService mapConsistencyService(String key) {
        return KeyBuilder.matchEphemeralKey(key) ? ephemeralConsistencyService : persistentConsistencyService;
    }

Service實現了監聽器接口:
在這裏插入圖片描述

DistroConsistencyServiceImpl的listen臨時的

其實就是創建一個CopyOnWriteArrayList集合和key的映射,這個集合是可同時讀寫的,寫的時候會複製一份來寫,寫完再替換舊的,此時讀的可能是舊的數據。然後將key監聽器放到集合離去。

    @Override
    public void listen(String key, RecordListener listener) throws NacosException {
        if (!listeners.containsKey(key)) {//創建CopyOnWriteArrayList
            listeners.put(key, new CopyOnWriteArrayList<>());
        }
        //二次確認不重複添加
        if (listeners.get(key).contains(listener)) {
            return;
        }
        //添加到創建CopyOnWriteArrayList
        listeners.get(key).add(listener);
    }

ServiceManager的addInstance添加實例

服務創建好了,監聽也加好了,接下來就要添加實例了。這裏再次獲取一次,看是不是爲空,空說明可能沒心跳被移除了。
在這裏插入圖片描述
如果存才的話添加實例:

    public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips) throws NacosException {
		//獲得服務實例key
        String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
		//再次獲取服務
        Service service = getService(namespaceId, serviceName);
        //這裏再判斷下service是否爲null比較好,因爲可能這個時候也爲空,synchronized鎖空對象會報異常,空對象沒monitor了
        synchronized (service) {
        	//獲取所有該服務的實例
            List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);

            Instances instances = new Instances();
            instances.setInstanceList(instanceList);//設置到包裝對象裏
			//放進一致性服務裏,其實就是放進臨時一致性服務內
            consistencyService.put(key, instances);
        }
    }

具體的裏面細節下次說吧。

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

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