当前位置: 首页 > 科技观察

SpringCloud集成Nacos服务发现源码解析?翻了三套源码,保持品质和新鲜感!

时间:2023-03-14 18:06:36 科技观察

本文转载自微信公众号《程序新视界》,作者二师兄丑胖子。转载本文请联系程序新视界公众号。前言在上一篇文章中,我们介绍了Nacos的功能和设计架构。本文主要围绕Nacos提供的服务注册功能,讲解Nacos的客户端是如何在SpringCloud中集成实现的。本次会议将配合源码分析、流程图整理、核心API解析等维度,让大家深入浅出、系统学习。SpringBoot的自动注册故事要从SpringBoot的自动注入说起。很多朋友可能都知道SpringBoot的自动配置功能,而SpringCloud是基于SpringBoot框架构建的。因此,在学习Nacos注册业务之前,我们先来回顾一下SpringBoot的自动配置原理,这也是学习的切入点。SpringBoot通过@EnableAutoConfiguration注解将所有符合条件的@Configuration配置加载到当前SpringBoot创建和使用的IoC容器中。上面的过程就是通过@Import(AutoConfigurationImportSelector.class)导入的配置函数。AutoConfigurationImportSelector中的getCandidateConfigurations方法获取到要配置的类的类名集合,即所有需要自动配置的(xxxAutoConfiguration)类。这些类在META-INF/spring.factories文件中配置。最后根据这些全限定类上的注解,如:OnClassCondition、OnBeanCondition、OnWebApplicationCondition条件决定是否自动配置。了解了SpringBoot的基本配置之后,我们来看看Nacos对应的自动配置在哪里。SpringCloud中Nacos自动配置查看SpringCloud的项目依赖。我引入了依赖对应的jar包为spring-cloud-starter-alibaba-nacos-discovery-2021.1.jar;对应的pom依赖为:com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discovery查看META-的内容jar包中的INF/spring.factories文件:org.springframework。boot.autoconfigure.EnableAutoConfiguration=\com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\com.alibaba.云.nacos.discovery.NacosDiscoveryClientConfiguration,\com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\com.alibabaService.clouds.nacos.Naprwork.cloud.bootstrap.BootstrapConfiguration=\com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration可以看到EnableAutoConfiguration类对应一系列Nacos自动配置类。其中NacosServiceRegistryAutoConfiguration用于封装实例化Nacos注册流程所需的组件。它加载了三个对象NacosServiceRegistry和NacosRegistration,NacosAutoServiceRegistration,这三个对象整体用于Nacos服务注册。@Configuration(proxyBeanMethods=false)@EnableConfigurationProperties@ConditionalOnNacosDiscoveryEnabled@ConditionalOnProperty(value="spring.cloud.service-registry.auto-registration.enabled",matchIfMissing=true)@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class,AutoServiceRegistrationAutoConfiguration.class,NacosDiscoveryAutoConfiguration.class})publicclassNacosServiceRegistryAutoConfiguration{@BeanpublicNacosServiceRegistrynacosServiceRegistry(NacosDiscoveryPropertiesnacosDiscoveryProperties){returnnewNacosServiceRegistry(nacosDiscoveryProperties);}@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)publicNacosRegistrationnacosRegistration(ObjectProvider>registrationCustomizers,NacosDiscoveryPropertiesnacosDiscoveryProperties,ApplicationContextcontext){returnnewNacosRegistration(registrationCustomizers.getIfAvailable(),nacosDiscoveryProperties,上下文);}@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)publicNacosAutoServiceRegistrationnacosAutoServiceRegistration(NacosServiceRegistryregistry,AutoServiceRegistrationPropertiesautoServiceRegistrationProperties,NacosRegistrationregistration){returnnewNacosAutoServiceRegistration(registry,autoServiceRegistrationProperties,registration);}}其中NacosServiceRegistry封装的就是注册流程,它继承自ServiceRegistry:publicclassNacosServiceRegistryimplementsServiceRegistry{...}查看该类源码,可以看到这个类实现了服务注册、注销、关机、设置状态、获取状态五个功能。我们要跟踪的服务注册功能是通过其提供的register方法实现的。至此,我们就可以梳理出Nacos客户端在SpringCloud中集成和实例化的处理流程了。上面提到了SpringCloud的ServiceRegistry接口,NacosServiceRegistry是从ServiceRegistry集成而来,那么ServiceRegistry到底是何方神圣呢?ServiceRegistry接口是SpringCloud的一个类。我们看一下ServiceRegistry接口的定义:publicinterfaceServiceRegistry{voidregister(Rregistration);voidderegister(Rregistration);voidclose();voidsetStatus(Rregistration,Stringstatus);TgetStatus(Rregistration);}可以看出ServiceRegistry接口定义了服务注册、注销、关闭、设置状态、获取状态五个接口。看看其他集成了SpringCloud的服务发现框架,基本上都是实现了这个接口。也就是说,ServiceRegistry是SpringCloud提供的服务发现框架集成规范。相应的框架安装规范实现相应的功能,可以集成。我们可以看到SpringCloud中Eureka、Zookeeper、Consul的集成也实现了这个接口。同时,如果你需要自定义服务发现功能,也可以通过实现这个接口来达到你的目的。NacosServiceRegistry服务注册实现暂时不关注其他辅助类,直接看NacosServiceRegistry#register方法,它提供了服务注册的核心业务逻辑实现。我们去掉这个类的辅助判断,直接展示核心代码如下:@Overridepublicvoidregister(Registrationregistration){//GetNamingServiceNamingServicenamingService=namingService();StringserviceId=registration.getServiceId();Stringgroup=nacosDiscoveryProperties.getGroup();//构造实例,封装信息来自配置属性Instanceinstance=getNacosInstanceFromRegistration(registration);//注册实例namingService.registerInstance(serviceId,group,instance);}上面代码中,NamingService已经属于提供的API支持通过NacosClient项目。关于NacosClient的API流程视图,可以直接查看Nacos对应的源码。NamingService#registerInstance方法对应的流程图整理如下:上面的流程图还可以进一步细化。我们将在后续章节中对此进行解释。每个人都知道这里。调用过程就够了。SpringCloud服务注册链接下面我们来梳理一下SpringCloud是如何进行服务注册的。所有服务注册框架的前三分之二过程几乎相同。注册实例时只会调用最后一部分。具体实施框架。直接看整个调用的链接图:图中不同的颜色代表不同的框架,灰色代表业务代码,浅绿色代表SpringBoot框架,深绿色代表Spring框架,浅橙色代表SpringCloud框架,其中还包含了依赖中Nacos组件部分,最后一个浅紫色代表NacosClient的包。核心流程分为以下几个步骤:首先,SpringBoot在启动main方法时调用Spring的核心方法refresh;其次,实例化Spring中的WebServerStartStopLifecycle对象。关注WebServerStartStopLifecycle对象。当它的start方法被调用时,会发布一个ServletWebServerInitializedEvent事件类,该类继承自WebServerInitializedEvent。后面用来处理服务注册的类AbstractAutoServiceRegistration也是一个监听器,专门用来监听WebServerInitializedEvent事件。第三步,AbstractApplicationContext的finishRefresh会间接调用DefaultLifecycleProcessor的startBeans方法,进而调用WebServerStartStopLifecycle的start方法。上面提到了ServletWebServerInitializedEvent事件的释放被触发。第四步,AbstractAutoServiceRegistration监听相应的事件,然后根据SpringCloud定义的ServiceRegistry接口进行服务注册。上面的描述省略了一些细节,但整个过程基本上就是SpringBoot启动时发布一个事件,SpringCloud监听相应的事件,然后注册服务。总结为了这篇文章,我肝了好几天。SpringCloud源码、SpringBoot源码、Nacos源码都搜过了。最后分享了Nacos或者SpringCloud中服务发现的实现机制和流程。