nacos源码服务注册

news2024/11/19 10:22:06

nacos服务注册

  • 序言
  • 1.源码环境搭建
    • 1.1idea运行源码
    • 1.2 登录nacos
  • 2.服务注册分析
    • 2.1 客户端
      • 2.1.1容器启动监听
      • 2.1.2注册前初始化
      • 2.1.3注册服务
    • 2.2 服务端
      • 2.2.1注册
      • 2.2.2重试机制
  • 3.注意事项

序言

本文章是分析的是nacos版本2.2
这次版本是一次重大升级优化,由原来(临时服务)服务注册tcp改成grpc方式,减少资源消耗,服务推送由udp也改为grpc

1.源码环境搭建

  • 源码下载

1.1idea运行源码

  • 导入
  • clean-install-reimport
    在这里插入图片描述
  • 配置
    在这里插入图片描述
  • 启动
    单机运行 启动项配置 VM option
    在这里插入图片描述

1.2 登录nacos

在这里插入图片描述

2.服务注册分析

2.1 客户端

首先让我去实现一个服务注册,我们如何去做?
思考一:
是不是项目启动的时候进行服务注册
思考二:
springboot自动装载,是不是引入nacos依赖,就可以实现服务注册功能

按照上面的思路去分析注册大概过程就很清晰了

2.1.1容器启动监听

  • 自动加载入口
 @Bean
    @ConditionalOnBean({AutoServiceRegistrationProperties.class})
    public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
        return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
    }
    
 public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
        super(serviceRegistry, autoServiceRegistrationProperties);
        this.registration = registration;
    }
  • web容器监听
public abstract class AbstractAutoServiceRegistration<R extends Registration> implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {

  • 綁定事件
    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.bind(event);
    }

    /** @deprecated */
    @Deprecated
    public void bind(WebServerInitializedEvent event) {
        ApplicationContext context = event.getApplicationContext();
        if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
            this.port.compareAndSet(0, event.getWebServer().getPort());
            this.start();
        }
    }
  public void start() {
        if (!this.isEnabled()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Discovery Lifecycle disabled. Not starting");
            }

        } else {
            if (!this.running.get()) {
                this.context.publishEvent(new InstancePreRegisteredEvent(this, this.getRegistration()));
                this.register();
                if (this.shouldRegisterManagement()) {
                    this.registerManagement();
                }

                this.context.publishEvent(new InstanceRegisteredEvent(this, this.getConfiguration()));
                this.running.compareAndSet(false, true);
            }

        }
    }

2.1.2注册前初始化

  • 获取namingservice服务
 public void register(Registration registration) {
       //创建namingservice服务
       NamingService namingService = this.namingService();
       //注册
       namingService.registerInstance(serviceId, group, instance);  
    }
  • 判断服务是否存在
  public NamingService getNamingService() {
        //不存在进行创建
        if (Objects.isNull(this.namingService)) {
            this.buildNamingService(this.nacosDiscoveryProperties.getNacosProperties());
        }

        return this.namingService;
    }
  • 创建NamingService服务
 NamingService naming = NamingFactory.createNamingService(properties);
 public NacosNamingService(Properties properties) throws NacosException {
        //nacosNamingService 客户端初始化
        init(properties);
    }
    
    private void init(Properties properties) throws NacosException {
        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);
        
        ValidatorUtils.checkInitParam(nacosClientProperties);
        //获取命名空间
        this.namespace = InitUtils.initNamespaceForNaming(nacosClientProperties);
        InitUtils.initSerialization();
        InitUtils.initWebRootContext(nacosClientProperties);
        initLogName(nacosClientProperties);
        //通知时间范围
        this.notifierEventScope = UUID.randomUUID().toString();
        //改变消息通知者
        this.changeNotifier = new InstancesChangeNotifier(this.notifierEventScope);
        //消息中心注册事件
        NotifyCenter.registerToPublisher(InstancesChangeEvent.class, 16384);
        //注册订阅者
        NotifyCenter.registerSubscriber(changeNotifier);
        //服务信息持有者
        this.serviceInfoHolder = new ServiceInfoHolder(namespace, this.notifierEventScope, nacosClientProperties);
        //创建客户端代理 去委托NamingClientProxyDelegate
        this.clientProxy = new NamingClientProxyDelegate(this.namespace, serviceInfoHolder, nacosClientProperties, changeNotifier);
    }

2.1.3注册服务

   public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
        NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
                instance);
        //缓存实例数据,增强可靠性
        redoService.cacheInstanceForRedo(serviceName, groupName, instance);
        //注册
        doRegisterService(serviceName, groupName, instance);
    }
 public void doRegisterService(String serviceName, String groupName, Instance instance) throws NacosException {
        InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
                NamingRemoteConstants.REGISTER_INSTANCE, instance);
        //请求注册
        requestToServer(request, Response.class);
        //设置缓存数据状态为已经注册状态
        redoService.instanceRegistered(serviceName, groupName);
    }

2.2 服务端

2.2.1注册

    private InstanceResponse registerInstance(Service service, InstanceRequest request, RequestMeta meta)
            throws NacosException {
        clientOperationService.registerInstance(service, request.getInstance(), meta.getConnectionId());
        NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),
                meta.getClientIp(), true, service.getNamespace(), service.getGroup(), service.getName(),
                request.getInstance().getIp(), request.getInstance().getPort()));
        return new InstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);
    }
    @Override
    public void registerInstance(Service service, Instance instance, String clientId) throws NacosException {
        NamingUtils.checkInstanceIsLegal(instance);
        //获取当前的 Service (没有就新创建)
        Service singleton = ServiceManager.getInstance().getSingleton(service);
        if (!singleton.isEphemeral()) {
            throw new NacosRuntimeException(NacosException.INVALID_PARAM,
                    String.format("Current service %s is persistent service, can't register ephemeral instance.",
                            singleton.getGroupedServiceName()));
        }
        Client client = clientManager.getClient(clientId);
        if (!clientIsLegal(client, clientId)) {
            return;
        }
        InstancePublishInfo instanceInfo = getPublishInfo(instance);
        client.addServiceInstance(singleton, instanceInfo);
        client.setLastUpdatedTime();
        client.recalculateRevision();
        // 发布通知注册时间
        NotifyCenter.publishEvent(new ClientOperationEvent.ClientRegisterServiceEvent(singleton, clientId));
        NotifyCenter
                .publishEvent(new MetadataEvent.InstanceMetadataEvent(singleton, instanceInfo.getMetadataId(), false));
    }
    

2.2.2重试机制

为了确保注册成功,会从缓存中,把注册状态为失败的注册实例进行重新注册

   public NamingGrpcRedoService(NamingGrpcClientProxy clientProxy) {
        this.redoExecutor = new ScheduledThreadPoolExecutor(REDO_THREAD, new NameThreadFactory(REDO_THREAD_NAME));
        this.redoExecutor.scheduleWithFixedDelay(new RedoScheduledTask(clientProxy, this), DEFAULT_REDO_DELAY,
                DEFAULT_REDO_DELAY, TimeUnit.MILLISECONDS);
    }
    public void run() {
        if (!redoService.isConnected()) {
            LogUtils.NAMING_LOGGER.warn("Grpc Connection is disconnect, skip current redo task");
            return;
        }
        try {
            //重新注册
            redoForInstances();
            //重新订阅
            redoForSubscribes();
        } catch (Exception e) {
            LogUtils.NAMING_LOGGER.warn("Redo task run with unexpected exception: ", e);
        }
    }

3.注意事项

  • idea 运行源码找不到类
    这时,你需要clean 再install 最后reimport,就不会问题
    在这里插入图片描述

  • 启动时nacos没有以单例模式启动也会报错

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL | 基础篇】02、MySQL 函数详解

目录 一、字符串函数 1.1 concat : 字符串拼接 1.2 lower : 全部转小写 1.3 upper : 全部转大写 1.4 lpad : 左填充 1.5 rpad : 右填充 1.6 trim : 去除空格 1.7 substring : 截取子字符串 1.8 案例 二、数值函数 2.1 ceil&#xff1a;向上取整 2.2 floor&#xff…

【Java版oj】day34收件人列表、养兔子

目录 一、收件人列表 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 二、养兔子 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 一、收件人列表 …

Python机器学习:支持向量机2

昨天是简单的了解了一下支持向量机要干什么以及线性可分支持向量机是怎么一回事&#xff0c;今年来看另一种&#xff1a;线性支持向量机&#xff1a; 我们昨天说的&#xff0c;线性可分支持向量机的目的就是找到一个超平面来吧一个数据集分成正负两个部分&#xff0c;但是实际…

一天学完C++的标准模板库STL

标准模板库STLstring字符串如何对string字符串的初始化&#xff08;声明&#xff09;&#xff1f;如何遍历string对象进行访问&#xff1f;如何对string类型的字符串进行增删改查&#xff1f;对string字符串增加一些字符对string字符串删除一些字符对string字符串改动一些字符在…

【hello Linux】环境变量

目录 1. 环境变量的概念 2. 常见的环境变量 3. 查看环境变量 4. 和环境变量相关的命令 5. 环境变量的组织方式 6. 通过代码获取环境变量 7. 通过系统调用获取环境变量 Linux&#x1f337; 在开始今天的内容之前&#xff0c;先来看一幅图片吧&#xff01; 不知道你们是否和我一…

数据结构的加强甜点-序列1

目录 尾递归 问题 介绍 特点 原理 答案 数组栈堆内存分配 前言 分析 再分析 所谓多维数组 程序局部性原理应用 尾递归 问题 在空间复杂度这块&#xff0c;有个O(n)示例如下&#xff1a; void recur(int n) {if (n 1) return;return recur(n - 1); } 这很明显是…

Canal(1):Canal入门

1 什么是 Canal 阿里巴巴 B2B 公司&#xff0c;因为业务的特性&#xff0c;卖家主要集中在国内&#xff0c;买家主要集中在国外&#xff0c;所以衍生出了同步杭州和美国异地机房的需求&#xff0c;从 2010 年开始&#xff0c;阿里系公司开始逐步的尝试基于数据库的日志解析&am…

SpringSecurity之微服务权限解决方案

目录 前置知识点 什么是微服务 微服务的优劣 优点 缺点 微服务本质 微服务认证与授权实现思路 认证预授权的过程 前置知识点 什么是微服务 微服务&#xff08;或称微服务架构&#xff09;是一种云 原 生 架构方法&#xff0c;在单个应用中包含众多松散耦合而且可单独部…

君子生非异也,善假于物也。【借助外力获取能量,主动改善生存环境。】

文章目录 引言I 借助外力1.1 制造很实用工具1.2 火引言 人类懂得借助外力,从被动地适应环境的进化,进入到主动改善生存环境的发展轨道上了。 人之所以为人,是因为我们善于借助外力,而不是先天有多少优势。 I 借助外力 学会制造和使用工具,提高能量获取的效率学会使用火,…

苹果手写笔有必要买吗?性价比电容笔排行榜

众所周知&#xff0c;苹果的正版Pencil的售价过于的高&#xff0c;一般的用户是买不起的。那么&#xff0c;市场上是否会有一款苹果Pencil的平替电容笔&#xff0c;而这两款电容笔在功能上是完全相同的&#xff1f;的确如此。国内的平替电容笔在书写方面上跟苹果Pencil差别不大…

【多线程的应用】顺序打印

【多线程的应用】顺序打印题目注意点&#xff1a;1. 每个线程循环10次&#xff0c;利用锁的wait 和 计数器count调节线程的执行顺序2. count后 lock.notifyAll 唤醒所有线程3. Thread.currentThread().getName()4. 锁中的逻辑是&#xff1a;进入锁中后&#xff0c;如果while不满…

图片怎么转换成pdf格式?这几个方法帮你一键转换

现今电子书籍越来越受到欢迎&#xff0c;其中PDF格式也成为了一种常用的电子书籍格式。无论是工作还是学习&#xff0c;我们都可能会遇到需要将图片转换成PDF格式的情况&#xff0c;例如保存一些资料证明、公文公告、学习资料等。在这篇文章中&#xff0c;我们将为大家介绍三种…

CT前瞻(一):Vant UI入门与使用

文章目录&#x1f4cb;前言&#x1f3af;什么是Vant UI&#x1f3af;快速上手&#x1f3af;组件用法&#x1f4dd;最后&#x1f4cb;前言 最近在项目开发和学习的过程中&#xff0c;涉及到了Vant UI&#xff08;简称Vant&#xff09;的使用&#xff0c;主要还是涉及到了Card卡…

[图神经网络]视觉图神经网络ViG(Vision GNN)--论文阅读

国际惯例&#xff1a; 论文地址https://arxiv.org/pdf/2206.00272.pdfgit地址https://github.com/huawei-noah/Efficient-AI-Backbones/tree/master/vig_pytorch 相较于之前将GNN和CNN结合的图像处理算法&#xff0c;ViG创新的将GNN直接用在了特征提取上。不再需要借用…

Docker快速搭建SkyWalking[ OAP UI[登录] Elasticsearch]

文章目录[前置]&#xff1a;搭建ELasticsearch相关[零]&#xff1a;虚拟机开放SkyingWalking和ES相关端口[一]&#xff1a;拉取SkyWalking-oap和SkyWalking-ui镜像[二]&#xff1a; 运行SkyWalking的oap和ui 容器 2.1 - 运行Skywalking-oap容器 ---- 注意oap运行参数异常 no pr…

早有尔闻 | 数字赋能,提质增效

01 卡奥斯牵头国家重点研发项目 助力中小企业数字化转型升级 3月24日&#xff0c;2022年国家重点研发计划“面向中小企业研发制造资源技术工业互联技术服务平台”项目正式启动。其中&#xff0c;卡奥斯COSMOPlat作为平台承建方牵头课题4“研发制造资源工业互联技术服务平台研…

CDH6.3.2引入debezium-connector-mysql-1.9.7监听mysql事件

1、首先说明一下为啥选用debezium&#xff0c;它能够根据事务的提交顺序向外推送数据&#xff0c;这一点非常重要。再有一个结合kafka集群能够保证高可用&#xff0c;对于熟悉java语言的朋友后面一篇博文会介绍怎样编写插件将事件自定义路由到你想要的主题甚至分区中。 提高按顺…

百度「文心一言」阿里「通义千问」腾讯的AI将会叫什么呢

阿里于昨天2023.4.7下午上线通义千问&#xff0c;与ChatGPT类似&#xff0c;同样是基于语言模型训练的人工智能聊天平台。通义千问的核心功能分为四个大类&#xff1a;撰写短文、职场助理、电影脚本和写封邮件。 通义千问通义千问https://tongyi.aliyun.com/ 首页如下&#xf…

word文件上的电子签章的法律效力如何保证?

你有没有见过这样的word文件“电子签章”&#xff1f; 这种用PS制作的“电子签章”&#xff0c;或者在一些输入公司名称就能在线生成“电子签章”的小网站、小作坊买来的“电子签章”&#xff0c;通通都是没有法律效力的贴图章&#xff01; 使用贴图章的word文件不但没有任何…

VsCode 将源代码管理(Working tree)中的新旧代码上下对比变为左右对比

文章目录一、默认设置二、左右布局变成了上下布局三、解决方法&#xff1a;将上下布局改为左右布局1&#xff1a;找到右上角的更多设置2&#xff1a;点击更多设置后点击【切换到并排视图】3&#xff1a;效果如下&#xff08;还是原来的效果&#xff09;四、左右切换成上下总结一…