Nacos的服务注册之客户端

news2024/12/24 22:13:34

服务注册到Nacos以后,会保存在一个本地注册表中,这个注册表是一个map.
private Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();

key是namespace,用来隔离环境
value又是一个map
     key是group
     value又是一个service
          service中又维护了一个map
            key是服务的某个集群的名称
            value是Cluster类型
                 Cluster内部又维护了一个set< Instance >集合,该集合就是集群下的实例的集合
                 Instance:包含石榴的IP、Port、健康状态、权重等信息
每一服务注册到Nacos时,就会把信息组织并存入这个Map中.

服务注册接口

nacos提供了服务注册的API接口,客户端只需要向该接口发送请求,即可实现服务注册.
请求接口: /nacos/v1/ns/instance

客户端

首先我们需要找到服务注册的入口.

NacosServiceRegistryAutoConfiguration
因为Nacos的客户端是基于SpringBoot的自动装配实现的,我们可以在nacos-discovery依赖:
spring-cloud-starter-alibaba-nacos-discovery-2.2.3.RELEASE.jar
在这里插入图片描述
可以看到,很多配置个配置类被夹在了,其中跟服务注册有关的就是NacosServiceRegistryAutoConfiguration
在这里插入图片描述
NacosAutoServiceRegistration
看看他构造器:
在这里插入图片描述
可以看到AbstractAutoServiceRegistration也被初始化了
在这里插入图片描述
从实现关系上,可以看到其实AbstractAutoServiceRegistration是一个监听器,监听的事件是WebServerInitializedEvent(服务初始化完成),当监听到该事件之后,就会执行对应的bind方法.

    public void bind(WebServerInitializedEvent event) {
    	// 获取上下文
        ApplicationContext context = event.getApplicationContext();
        // // 判断服务的 namespace,一般都是null
        if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
        	// 记录当前 web 服务的端口
            this.port.compareAndSet(0, event.getWebServer().getPort());
            // 启动当前服务注册流程
            this.start();
        }
    }

我们来看他的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()));
                // 服务状态设置为运行中,基于AtomicBoolean
                this.running.compareAndSet(false, true);
            }

        }
    }

这里最关键的就是this.register();方法.

    protected void register() {
        this.serviceRegistry.register(this.getRegistration());
    }

从源码中,我们可以看到serviceRegistry的实现类NacosServiceRegistry
NacosServiceRegistry
ServiceRegistry接口是服务注册、发现的规约接口,定义了register、deregister等方法的声明。

    public void register(Registration registration) {
    	// 判断serviceId是否为空,也就是spring.application.name不能为空
        if (StringUtils.isEmpty(registration.getServiceId())) {
            log.warn("No service to register for nacos client...");
        } else {
        	// 获取 serviceId 和 Group
            String serviceId = registration.getServiceId();
            String group = this.nacosDiscoveryProperties.getGroup();
            // 封装服务实例的基本信息,如cluster-name、是否为临时实例、权重、IP、端口号等
            Instance instance = this.getNacosInstanceFromRegistration(registration);

            try {
            	// namingService:Nacos的命名服务,就是注册中心服务
            	// 开始注册服务
                this.namingService.registerInstance(serviceId, group, instance);
                log.info("nacos registry, {} {} {}:{} register finished", new Object[]{group, serviceId, instance.getIp(), instance.getPort()});
            } catch (Exception var6) {
                log.error("nacos registry, {} register failed...{},", new Object[]{serviceId, registration.toString(), var6});
            }

        }
    }

其中namingService的registerInstance方法真正进行注册

    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
		// 是否是临时实例,如果是的话,需要 定时发送心跳
		// 默认是true
        if (instance.isEphemeral()) {
            BeatInfo beatInfo = new BeatInfo();
            beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
            beatInfo.setIp(instance.getIp());
            beatInfo.setPort(instance.getPort());
            beatInfo.setCluster(instance.getClusterName());
            beatInfo.setWeight(instance.getWeight());
            beatInfo.setMetadata(instance.getMetadata());
            beatInfo.setScheduled(false);
            beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());

            // 发送心跳到 Nacos 服务
            beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
        }
		// 拼接得到新的服务名,格式为:groupName@@serviceId
		// 发送注册服务实例的请求
        serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
    }

我们接着看serverProxy里的registerService方法

    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {

        NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}",
            namespaceId, serviceName, instance);

		// 组织参数
        final Map<String, String> params = new HashMap<String, String>(9);
        params.put(CommonParams.NAMESPACE_ID, namespaceId);
        params.put(CommonParams.SERVICE_NAME, serviceName);
        params.put(CommonParams.GROUP_NAME, groupName);
        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
        params.put("ip", instance.getIp());
        params.put("port", String.valueOf(instance.getPort()));
        params.put("weight", String.valueOf(instance.getWeight()));
        params.put("enable", String.valueOf(instance.isEnabled()));
        params.put("healthy", String.valueOf(instance.isHealthy()));
        params.put("ephemeral", String.valueOf(instance.isEphemeral()));
        params.put("metadata", JSON.toJSONString(instance.getMetadata()));
		
		// 请求api
        reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);

    }

客户端注册的流程图
在这里插入图片描述
上面讲的就是客户端注册如何调用接口进行注册的,后面服务端会对客户端的请求做一系列的处理.因为服务端做的处理还是挺复杂的,下一篇文章再分析吧.

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

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

相关文章

java计算机毕业设计springboot+vue远程教育系统

项目介绍 通篇文章的撰写基础是实际的应用需要,然后在架构系统之前全面复习大学所修习的相关知识以及网络提供的技术应用教程,以远程教育系统的实际应用需要出发,架构系统来改善现远程教育系统工作流程繁琐等问题。不仅如此以操作者的角度来说,该系统的架构能够对多媒体课程进…

以太网 DHCP(简介、DHCP工作原理、租期时间)

2.13.0 以太网 DHCP&#xff08;简介、DHCP工作原理、租期时间&#xff09; DHCP的作用&#xff1a;企业网络中存在大量的终端设备&#xff08;PC&#xff09;&#xff0c;管理员配置设备上网参数工作量大&#xff0c;而且效率不高&#xff0c;手动配置容易出错&#xff0c;DH…

数据库复杂sql如何编写入手

前言&#xff1a;说到数据库我想大家都不陌生&#xff0c;对主流的数据库都会基本使用&#xff0c;但是要写好sql完成复杂的sql编写是需要对数据库原理&#xff0c;sql脚本语法有一定的了解的&#xff0c;但是对于开发人员来说&#xff0c;平常都是在curd写一些业务代码&#x…

Flutter 中使用 OpenAI GPT-3 进行语义化处理

Flutter 中使用 OpenAI GPT-3 进行语义化处理 前言 最近 openai 的 ChatGPT 火了&#xff0c;然后我也想着用它来做点什么&#xff0c;于是就写了个 调用 openai api 语言执行工具&#xff0c;跑个测试&#xff0c;以后再有功能也可以在这个程序上面试验。 copilot 也是用的 op…

m基于FPGA的64QAM调制解调、载波同步verilog实现

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 64QAM&#xff08;正交幅度调制&#xff09;&#xff0c;在使用同轴电缆的网络中&#xff0c;这种数字频率调制技术通常用于发送下行链路数据。64QAM在6mhz信道中&#xff0c;64QAM的传输速率非常…

Qt编写视频监控系统(移动侦测/遮挡报警/区域入侵/越界侦测/报警输入输出等)

一、前言 得益于标准的onvif协议&#xff0c;各大监控厂商的设备都会支持onvif协议&#xff0c;在onvif协议中就包括了事件订阅机制&#xff0c;通过这个机制&#xff0c;可以拿到各种报警事件&#xff0c;比如移动侦测/遮挡报警/区域入侵/越界侦测/报警输入输出等&#xff0c…

深度学习-环境搭建(安装Pytorch)

文章目录前言一、安装Anaconda二、查看电脑显卡支持的CUDA版本三、更新CUDA版本四、创建并激活Anaconda虚拟环境需要创建虚拟环境而最好不在base下载的原因五、安装pytorchPS&#xff1a;注意事项六、下载其他库七、检查安装结果总结前言 入门深度学习过程中&#xff0c;我决定…

[附源码]JAVA毕业设计鞋店销售管理(系统+LW)

[附源码]JAVA毕业设计鞋店销售管理&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

都在说软件测试真的干不到35岁,那咋办呢...我都36了...

作为一个已经36岁但仍奋战在测试一线的老测试员&#xff0c;被人无数次问到这个问题&#xff0c;也回答过无数次&#xff0c;刚看到 程序员真的干到35岁就干不动了吗 想到&#xff0c;在测试行业&#xff0c;也有很多年轻人在焦虑这个问题。现在小编就从管理、技术、思维、体力…

Pytho——naiohttp的简单使用

1.aiohttp的简单使用(配合asyncio模块) import asyncio,aiohttpasync def fetch_async(url):print(url)async with aiohttp.request("GET",url) as r:reponse await r.text(encoding"utf-8")  #或者直接await r.read()不编码&#xff0c;直接读取&…

我不谈ChatGPT

&#xff08;1&#xff09;数据有两个未经证实的传闻&#xff1a;1、客服问答&#xff1a;80%用户问的问题都是那20%常见问题&#xff0c;但是就是这样&#xff0c;占用了客服人员80%的工作量和工作时间2、资讯搜索&#xff1a;谷歌一位员工说&#xff0c;在互联网上&#xff0…

Spring Cloud Alibaba-全面详解(学习总结---从入门到深化)

​​​​​​​ Spring Cloud Alibaba简介 什么是Spring Cloud Alibaba Spring Cloud Alibaba致力于提供微服务开发的一站式解决方案。 此项目包含开发分布式应用微服务的必需组件&#xff0c;方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。 为…

OSI七层模型中各层网络协议

应用层: (典型设备:应用程序&#xff0c;如FTP&#xff0c;SMTP &#xff0c;HTTP) DHCP(Dynamic Host Configuration Protocol)动态主机分配协议&#xff0c;使用 UDP 协议工作&#xff0c;主要有两个用途&#xff1a;给内部网络或网络服务供应商自动分配 IP 地址&#xff0c…

spring——Spring 注入内部Bean——setter 方式注入内部 Bean

我们将定义在 <bean> 元素的 <property> 或 <constructor-arg> 元素内部的 Bean&#xff0c;称为“内部 Bean”。 项目依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org…

交战“低代码”,云大厂跑马圈地

者 关注 2022年末,云大厂阿里、腾讯、华为(ATH)开始了新一轮的跑马圈地。 这一次交战的战场,是低代码。 11月18日,华为AppCube全线产品全面升级,在低代码、零代码、数据看板三个方面,升级优化;11月13日,腾讯升级了云开发开发者工具“微搭”,目前已服务开发者数300万…

疫情期间,家中常备药物有哪些?这份清单请收好

【防疫科普】疫情期间&#xff0c;家中常备药物有哪些&#xff1f;这份清单请收好 为加强防疫知识科普&#xff0c;提振群众战“疫”必胜信心&#xff0c;疫情期间&#xff0c;我们将持续向广大市民朋友传递科学健康科普知识、防疫提醒、自我防护注意事项、疫情期间心理疏导等相…

Python融于ASP框架

一、ASP的平反 想到ASP 很多人会说 “asp语言很蛋疼&#xff0c;不能面向对象&#xff0c;功能单一&#xff0c;很多东西实现不了” 等等诸如此类。 以上说法都是错误的&#xff0c;其一ASp不是一种语言是 微软用来代替CGI的一种web框架&#xff0c;只不过我们一直被扭曲在 vbs…

计算机毕业设计php_thinkphp_vue的校园论坛网站

运行环境 开发语言&#xff1a;PHP 数据库:MYSQL数据库 应用服务:apache服务器 使用框架:ThinkPHP&#xff1a;vue 开发工具:VScode/Dreamweaver/PhpStorm等均可 项目简介 在各学校的校园论坛中,交流是一项非常重要的事情。随着计算机多媒体技术的发展和网络的普及。采用当前流…

Python 数据库开发实战 - Redis命令行客户端与图形客户端的简单使用

上一章节我们已经启动了 redis 服务器&#xff0c;在这一章节我们就爱你过来学习 redis命令行客户端与图形客户端的简单使用&#xff0c;以及 redis 的 一些关键参数。 Redis 命令行客户端 - redis-cli redis-cli 是 Redis 自带的 命令行终端界面&#xff0c;一个简单的程序&…

【Redis】Redis 分布式锁误删问题

本文主要介绍 Redis 分布式锁误删问题的解决 场景一 1. 问题的产生情况一 因为业务阻塞&#xff0c;导致别人的锁被误删 2. 解决思路 获取锁的时候存入标识&#xff0c;释放锁的时候判断标识是否一致&#xff0c;一致可以释放锁&#xff0c;不一致不释放锁。 3. 解决代码 …