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

客户端注册实例流程

202309152318231181.png

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实现了监听器接口:

202309152318236112.png

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添加实例

服务创建好了,监听也加好了,接下来就要添加实例了。这里再次获取一次,看是不是为空,空说明可能没心跳被移除了。

202309152318240523.png
如果存才的话添加实例:

        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);
            }
        }

具体的里面细节下次说吧。

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

阅读全文