服务启动何时触发 Nacos 的注册流程?

前言:

前面的系列文章让我们对 Nacos 有了一个基本了解,并知道了如何去试用 Nacos 作为注册中心和配置中心,本篇我们将从源码层面去分析 Nacos 的服务注册流程。

Nacos 系列文章传送门:

Nacos 初步认识和 Nacos 部署细节

Nacos 配置管理模型 – 命名空间(Namespace)、配置分组(Group)和配置集ID(Data ID)

Nacos 注册中心和配置中心【实战】

服务启动何时触发 Nacos 的注册流程?

想要知道服务是如何注册到 Nacos 的最简单方法就是启动我们的微服务,跟着启动流程走可以了,Spring Boot 项目的启动流程源码之前已经分析过,这里不再详细分析,我们只看跟服务注册有关的核心代码,我们知道 Spring Boot 启动后,会调用到 AbstractApplicationContext#finishRefresh 方法,如下:

//完成后刷新
protected void finishRefresh() {//清除资源缓存this.clearResourceCaches();//初始化生命周期处理器this.initLifecycleProcessor();//将刷新完成事件广播到 生命周期处理器this.getLifecycleProcessor().onRefresh();//广播容器刷新完成事件this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));if (!NativeDetector.inNativeImage()) {//注册 ApplicationContext 到 LiveBeansView 内部的 applicationContexts 中LiveBeansView.registerApplicationContext(this);}}

我们重点关注 this.getLifecycleProcessor().onRefresh() 这行代码,这行代码的作用是将 IOC 容器刷新完成事件广播到生命周期处理器,这里回调处理的众多生命周期处理器中有一个叫做 WebServerStartStopLifecycle 的生命周期处理器,WebServerStartStopLifecycle 中有一个 start 方法,如下:

//org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle#start
public void start() {this.webServer.start();this.running = true;//发布 Web容器初始化完成 事件this.applicationContext.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}

在这里插入图片描述

我们可以看到 start 方法发布了一个 ServletWebServerInitializedEvent 容器初始化完成事件,根据 Spring 的事件发布机制可以知道,肯定会有某个监听器监听了这个事件,我们发现 org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration 这个类监听了 ServletWebServerInitializedEvent 事件,因此一旦发布了 ServletWebServerInitializedEvent 事件,AbstractAutoServiceRegistration 就能马上感知到,并在 AbstractAutoServiceRegistration#onApplicationEvent 方法中进行相应的处理。

AbstractAutoServiceRegistration#onApplicationEvent 方法分析

AbstractAutoServiceRegistration#onApplicationEvent 方法是 WebServerInitializedEvent 事件的回调方法,调用了 AbstractAutoServiceRegistration#bind 方法。

//org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration#onApplicationEvent
public void onApplicationEvent(WebServerInitializedEvent event) {this.bind(event);
}

AbstractAutoServiceRegistration#bind 方法分析

AbstractAutoServiceRegistration#bind 方法进行简单的判断后继续调用了 AbstractAutoServiceRegistration#start 方法,发起服务注册。

//org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration#bind
@Deprecated
public void bind(WebServerInitializedEvent event) {//获取 ApplicationContextApplicationContext context = event.getApplicationContext();//判断服务的 namespaceif (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {//记录服务端口this.port.compareAndSet(0, event.getWebServer().getPort());//发起服务注册this.start();}
}

AbstractAutoServiceRegistration#start方法分析

AbstractAutoServiceRegistration#start方法进行简单的判断后继续调用了 AbstractAutoServiceRegistration#start ,调用了 NacosAutoServiceRegistration#register 方法发起服务注册,至此终于出现了 Nacos。

//com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration#register
protected void register() {//判断是否开启注册if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {log.debug("Registration disabled.");} else {if (this.registration.getPort() < 0) {this.registration.setPort(this.getPort().get());}//调用 AbstractAutoServiceRegistration#register 方法super.register();}
}

AbstractAutoServiceRegistration#register 方法分析

NacosAutoServiceRegistration#register 方法简单的判断服务是否开启注册后,继续调用了父类 AbstractAutoServiceRegistration#register,父类中的 serviceRegistry 是 NacosServiceRegistry 的一个实例,它是Spring Boot 在 NacosServiceRegistryAutoConfiguration 中自动注入的,最终是调用了 NacosServiceRegistry#register 方法完成服务注册。

//com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration#register
protected void register() {//判断是否开启注册if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {log.debug("Registration disabled.");} else {if (this.registration.getPort() < 0) {this.registration.setPort(this.getPort().get());}//调用父类 AbstractAutoServiceRegistration#register 方法super.register();}
}//org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration#register
protected void register() {//调用 NacosServiceRegistry#register  方法完成服务注册this.serviceRegistry.register(this.getRegistration());
}

NacosServiceRegistryAutoConfiguration 方源码分析

这里直接附上 NacosServiceRegistryAutoConfiguration 源码,我们知道 NacosServiceRegistryAutoConfiguration 类是 Nacos 服务自动注册相关的配置类,是通过 Spring Boot 自动配置加载的,阅读源码,我们发现这个配置类并没有做其他的事情,只是注入了三个类,如下:

  • NacosServiceRegistry:完成服务注册功能,实现 ServiceRegistry 接口。
  • NacosRegistration:注册时用来存储 Nacos 服务端的相关信息。
  • NacosAutoServiceRegistration:真正完成 Nacos 自动注册功能。
package com.alibaba.cloud.nacos.registry;import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration(proxyBeanMethods = false
)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = {"spring.cloud.service-registry.auto-registration.enabled"},matchIfMissing = true
)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class})
public class NacosServiceRegistryAutoConfiguration {public NacosServiceRegistryAutoConfiguration() {}@Beanpublic NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {return new NacosServiceRegistry(nacosDiscoveryProperties);}@Bean@ConditionalOnBean({AutoServiceRegistrationProperties.class})public NacosRegistration nacosRegistration(ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers, NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {return new NacosRegistration((List)registrationCustomizers.getIfAvailable(), nacosDiscoveryProperties, context);}@Bean@ConditionalOnBean({AutoServiceRegistrationProperties.class})public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);}
}

至此,我们基本梳理清楚了 Nacos 的服务注册流程,简单总结如下:

  • 服务启动时候通过 Spring Boot 自动配置功能,自动加载了 META-INF/spring.factories中的 Nacos 服务注册的自动配置类 NacosServiceRegistryAutoConfiguration,而 NacosServiceRegistryAutoConfiguration 又往 Spring注入了三个重要的 Bean,NacosServiceRegistry、NacosRegistration、NacosAutoServiceRegistration。
  • 服务启动到最后会调用 AbstractApplicationContext#finishRefresh 方法,将 IOC 容器刷新完成事件广播到生命周期处理器,众多生命周期处理器中有一个叫做 WebServerStartStopLifecycle 的生命周期处理器,WebServerStartStopLifecycle 会发布了一个 ServletWebServerInitializedEvent 容器初始化完成事件。
  • AbstractAutoServiceRegistration 监听了 WebServerInitializedEvent 事件,执行服务注册。
  • NacosAutoServiceRegistration 重写了register 方法,最终会调用 NacosServiceRegistry#register 方法完成服务的自动注册。

总结:服务注册到 Nacos 流程的核心是使用了 Spring 的事件监听机制,虽然 Spring 的监听机制在我们平时写代码中几乎用不到,但是在框架源码中还是大量使用了的。

欢迎提出建议及对错误的地方指出纠正。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++基础学习笔记

1.命名空间(namespace) 1.什么是命名空间&命名空间的作用 1.在C/C中&#xff0c;变量、函数、类都是大量存在的&#xff0c;这些变量等的名称将都存在于全局作用域中&#xff0c;就会导致很多的命名冲突等。使用命名空间的目的就是对标识符的名称进行本地化&#xff0c;以…

短视频矩阵系统全解析:让获客变得更简单

随着数字媒体的迅猛发展&#xff0c;短视频已成为人们生活中不可或缺的一部分。对于企业而言&#xff0c;如何有效利用短视频平台吸引目标用户&#xff0c;实现高效获客&#xff0c;成为了一个亟待解决的问题。本文将全面解析短视频矩阵系统&#xff0c;带您领略其独特魅力&…

广度优先(BFS)

先看一道简单的题&#xff0c;迷宫问题&#xff1a; 洛谷P1746 离开中山路&#xff1a;P1746 离开中山路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> #include<cstring> #include<queue> #include <utility> #define N 1002 …

深度学习的数学PDF

链接: https://pan.baidu.com/s/1_jScZ7dcyAWGqbrad6bbCQ?pwd9gj9 提取码: 9gj9 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦

最简单的vue3组件之间传值

localStorage 是 HTML5 引入的一个 Web Storage API 的一部分&#xff0c;它允许网页在用户的浏览器上存储数据。localStorage 提供了一种持久化的本地存储方案&#xff0c;数据不会因为浏览器关闭而丢失&#xff0c;除非用户或脚本显式地删除它们。 localStorage 是一种非常实…

VSCode神仙插件——通义灵码 (AI编程助手)

1、安装&登录插件 安装时,右下角会有弹窗,让你登录该软件 同意登录后,会跳转浏览器页面 VSCode右下角出现如下图标即登录成功 2、使用 (1)点击左侧栏中的如下图标,打开通义灵码,可以进行智能问答 (2) 选中代码,右键 但是,上述所有的操作会在左侧问答栏中提供答案,并无法直…

认识并理解webSocket

今天逛牛客&#xff0c;看到有大佬分享说前端面试的时候遇到了关于webSocket的问题&#xff0c;一看自己都没见过这个知识点&#xff0c;赶紧学习一下&#xff0c;在此记录&#xff01; WebSocket 是一种网络通信协议&#xff0c;提供了全双工通信渠道&#xff0c;即客户端和服…

31. 1049. 最后一块石头的重量 II, 494.目标和,474.一和零

class Solution { public:int lastStoneWeightII(vector<int>& stones) {int sum 0;for(int stone : stones) sum stone;int bagSize sum /2;vector<int> dp(bagSize 1, 0);for(int i 0; i < stones.size(); i){ //遍历物品for(int j bagSize; j >…

LLMs的基本组成:向量、Tokens和嵌入

编者按&#xff1a;随着人工智能技术的不断发展&#xff0c;大模型&#xff08;语言、视觉&#xff0c;或多模态模型&#xff09;已成为当今AI应用的核心组成部分。这些模型具有处理和理解自然语言等模态输入的能力&#xff0c;推动了诸如聊天机器人、智能助手、自动文本生成等…

Android初学者书籍推荐

书单 1.《Android应用开发项目式教程》&#xff0c;机械工业出版社&#xff0c;2024年出版2.《第一行代码Android》第二版3.《第一行代码Android》第三版4.《疯狂Android讲义》第四版5.《Android移动应用基础教程&#xff08;Android Studio 第2版&#xff09;》 从学安卓到用安…

Node.js如何在Windows安装?

文章目录 主要特点&#xff1a;使用场景&#xff1a;安装方法验证是否安装成功 Node.js 是一个开源、跨平台的JavaScript运行环境&#xff0c;由Ryan Dahl于2009年创建。它允许开发者在服务器端运行JavaScript代码。Node.js 基于Chrome V8 JavaScript引擎构建&#xff0c;其设计…

项目/代码规范与Apifox介绍使用

目录 目录 一、项目规范&#xff1a; &#xff08;一&#xff09;项目结构&#xff1a; &#xff08;二&#xff09;传送的数据对象体 二、代码规范&#xff1a; &#xff08;一&#xff09;数据库命名规范&#xff1a; &#xff08;二&#xff09;注释规范&#xff1a; …

关于CANNM PassiveMode

Passive Mode的要求 根据上图CANNM的规范可知&#xff1a; 处于Passive Mode的网络节点只能接收网络管理PDU&#xff0c;不能发送网络管理PDU。Passive Mode由CanNmPassiveModeEnable参数静态配置。如果一个ECU包含多个节点&#xff0c;那么所有的节点要么都是Passive Mode要么…

GD32F303之CAN通信

1、CAN时钟 GD32F303主时钟频率最大是120Mhz,然后APB1时钟最大是60Mhz,APB2时钟最大是120Mhz,CAN挂载在APB1总线上面 所以一般CAN的时钟频率是60Mhz,这个频率和后面配置波特率有关 2、GD32F303时钟配置 首先我们知道芯片有几个时钟 HXTAL&#xff1a;高速外部时钟&#xff1…

elementui实现复杂表单的实践

简介 文章主要讲述在vue3项目中使用elementui框架实现复杂表单的方式。表单中涉及动态组件的生成、文件上传和富文本编辑器的使用&#xff0c;只会将在实现过程中较复杂的部分进行分享&#xff0c;然后提供一份完整的前端代码。 表单效果演示 基础信息 spu属性 sku详情 关键…

曝宝马汽车门店亏损严重价格战带来的伤害太大了

今年以来不仅餐饮行业难,就连一些车企都陷入困境当中,多家车企选择打价 格战。只不过日前的时候媒体爆料称,宝马汽车门店因为打价格战,最终亏损严 重,为了避免亏损再度出现,因此宝马7月将会开始降量保价。文章来源于&#xff1a;股城网www.gucheng.com 实际上,进入2024年…

如何在 C 语言中进行选择排序?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; &#x1f4d9;C 语言百万年薪修炼课程 通俗易懂&#xff0c;深入浅出&#xff0c;匠心打磨&#xff0c;死磕细节&#xff0c;6年迭代&#xff0c;看过的人都说好。 文章目…

B站大课堂-自动化精品视频(个人存档)

基础知识 工业通信协议 Modbus 施耐德研发&#xff0c;有基于以太网的 ModbusTCP 协议和使用 485/232 串口通信的 ModbusRTU/ASCII。 Modbus 协议面世较早、协议简洁高效、商用免费、功能灵活、实现简单&#xff0c;是目前应用最广泛的现场总线协议。 我的笔记里边有一些推荐…

本地开发微信小程序,使用巴比达内网穿透

在微信小程序开发的热潮中&#xff0c;开发者常面临的一个挑战是如何在复杂的网络环境下测试和调试内网环境中的服务。巴比达正为这一难题提供了一条解决方案&#xff0c;极大简化了微信小程序与内网服务器之间通信的流程&#xff0c;加速了开发迭代周期。 以往&#xff0c;开…

关于力反馈设备应用方向的探讨

力反馈是在虚拟现实 (VR)等模拟环境中通过机动运动或阻力模拟真实世界的物理触觉。大多数人都是通过视频游戏控制器&#xff08;如方向盘或踏板&#xff09;和其他设备&#xff08;如飞行模拟器操纵杆&#xff09;来了解力反馈效果。但我们都知道该技术的用途远不止于游戏。 触…