SpringCloud Nacos 【服务端】服务注册源码解析

1 环境介绍

nacos版本1.4.1

在这里插入图片描述

2 注册入口

描述: 查看nacos官网, 请求url为:

/nacos/v1/ns/instance

在这里插入图片描述

描述: 找到 InstanceController类,register方法。

   @CanDistro
    @PostMapping
    @Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
    public String register(HttpServletRequest request) throws Exception {
        
        final String namespaceId = WebUtils
                .optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
        final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
        NamingUtils.checkServiceNameFormat(serviceName);
        
        final Instance instance = parseInstance(request);
        
        /**
         * 服务端注册核心逻辑
         */
        serviceManager.registerInstance(namespaceId, serviceName, instance);
        return "ok";
    }

3 核心逻辑分析

3.1 ServiceManager

描述: service注册nacos核心类。

在这里插入图片描述

3.2 Nacos 注册表

描述: nacos注册表采用双map结构,一套nacos 可以配置多套项目,其结构可以理解为:

(1) namespace: 用于区分项目。
(2) group: 用于区分环境(dev、release)(3) servcieName:微服务名称.
(4) Service:真正的服务。

用group::servcieName 确定Service。

在这里插入图片描述

3.3 Service

描述: Nacos中服务端的服务,存储服务采用Map结构,其Key 代表集群名称(可以用于区分地区),Cluster用于存储服务端的服务。Cluster存储服务实例又分为持久服务集,临时服务集。
在这里插入图片描述

在这里插入图片描述

3.4 registerInstance 方法

描述: ServiceManager类registerInstance方法。

public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
        
        
        //创建一个空的service
        createEmptyService(namespaceId, serviceName, instance.isEphemeral());

        //获取service
        Service service = getService(namespaceId, serviceName);

        if (service == null) {
            throw new NacosException(NacosException.INVALID_PARAM,
                "service not found, namespace: " + namespaceId + ", service: " + serviceName);
        }
        //添加
        addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
    }

3.5 createEmptyService方法

描述: ServiceManager类createEmptyService方法。
在这里插入图片描述

  public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
        throws NacosException {
        //从注册表中获取服务
        Service service = getService(namespaceId, serviceName);
        
        //服务为空
        if (service == null) {
            Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
            //创建服务,初始化相关属性
            service = new Service();
            service.setName(serviceName);
            service.setNamespaceId(namespaceId);
            service.setGroupName(NamingUtils.getGroupName(serviceName));
            // now validate the service. if failed, exception will be thrown
            service.setLastModifiedMillis(System.currentTimeMillis());
            service.recalculateChecksum();
            if (cluster != null) {
                cluster.setService(service);
                service.getClusterMap().put(cluster.getName(), cluster);
            }
            service.validate();
            //添加服务到注册表中,并且初始化心跳检测
            putServiceAndInit(service);
            if (!local) {
                addOrReplaceService(service);
            }
        }
    }
private void putServiceAndInit(Service service) throws NacosException {
        //双重检测加入nacos注册表中
        putService(service);
		//采用scheduleWithFixedDelay定期检测心跳
        service.init();
        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());
    }

在这里插入图片描述

3.6 addInstance 方法

描述: 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);

        synchronized (service) {
            //ips转instances
            List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
            Instances instances = new Instances();
            instances.setInstanceList(instanceList);
            //一致性service存放instances
            consistencyService.put(key, instances);
        }
    }

在这里插入图片描述

3.7 DistroConsistencyServiceImpl

描述: put方法。
在这里插入图片描述
在这里插入图片描述
描述: 客户端向nacos发送注册请求,最终在Notifier阻塞队列中添加了注册任务。
在这里插入图片描述

4 Notifier 分析

描述: 任务启动,DistroConsistencyServiceImpl类初始化时,会初始化线程池开启Notifier 方法,并且当前线程corePoolSize为1。

在这里插入图片描述
在这里插入图片描述

描述: 当前类实现了Runnable接口,直接查看run方法。
在这里插入图片描述

@Override
        public void run() {
            Loggers.DISTRO.info("distro notifier started");

            //自旋
            for (; ; ) {
                try {
                    //从阻塞队列中获取任务
                    Pair<String, DataOperation> pair = tasks.take();
                    //处理
                    handle(pair);
                } catch (Throwable e) {
                    Loggers.DISTRO.error("[NACOS-DISTRO] Error while handling notifying task", e);
                }
            }
        }

4.1 handle方法。

在这里插入图片描述

4.2 onChange

描述: Service类onChange方法会调用,updateIPs方法进行服务端ip列表的更新。
在这里插入图片描述

4.3 updateIPs

在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

响彻天堂丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值