springcloudAlibaba之Nacos服务注册源码分析

Nacos服务注册源码分析

  • Nacos服务注册原理
  • Nacos服务注册怎么做的
  • Nacos服务注册源码解读

带着以上三个问题,进入到今天的源码解读

问题1:Nacos服务注册原理

Nacos首先从bootstrap.yml配置文件中读取我们配置好的nacos配置,这里面一般包括spring.application.name、spring.cloud.nacos.discovery.server-addr、spring.cloud.nacos.username、spring.cloud.nacos.password以及其他的一些例如cluster、namespace等信息,依托ConfigurationProperties注解 让spring将这些配置封装成一个对象,在容器刷新完成之后执行一个register方法,把当前应用注册到指定的Nacos服务端

问题2:Nacos服务注册怎么做的

我们知道 像这种第三方集成springboot的应用,一般都会使用starter封装起来,而starter的核心就是自动装配,那么我们只需要搜索类似nacosAutoconfig之类的 就应该可以找到

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不出所料 我们成功搜索到了几个类,大致可以分为三类 config配置中心、discovery注册中心以及ribbon负载均衡 ,目前我们关注的是注册中心 那么直接选择NacosDiscoveryAutoConfiguration即可。

@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(
    value = {"spring.cloud.service-registry.auto-registration.enabled"},
    matchIfMissing = true
)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class})
public class NacosDiscoveryAutoConfiguration {
    public NacosDiscoveryAutoConfiguration() {
    }

    @Bean
    public NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
        return new NacosServiceRegistry(nacosDiscoveryProperties);
    }

    @Bean
    @ConditionalOnBean({AutoServiceRegistrationProperties.class})
    public NacosRegistration nacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {
        return new NacosRegistration(nacosDiscoveryProperties, context);
    }

    @Bean
    @ConditionalOnBean({AutoServiceRegistrationProperties.class})
    public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
        return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
    }
}

通过观察这个类 可以看出来它是一个典型的springboot配置类,它里面干了三件事,也可以说是一件事,那就是注册Bean,第一、第二个bean是第三个bean的入参 ,说明第三个bean是重点,点进去之后发现这个类里面有一个register方法,盲猜 这个应该就是用来注册的方法,registration对象就是我们配置文件中的配置信息

    public void register(Registration registration) {
        if (StringUtils.isEmpty(registration.getServiceId())) {
            log.warn("No service to register for nacos client...");
        } else {
            String serviceId = registration.getServiceId();
            Instance instance = new Instance();
            instance.setIp(registration.getHost());
            instance.setPort(registration.getPort());
            instance.setWeight((double)this.nacosDiscoveryProperties.getWeight());
            instance.setClusterName(this.nacosDiscoveryProperties.getClusterName());
            instance.setMetadata(registration.getMetadata());

            try {
                this.namingService.registerInstance(serviceId, instance);
                ...
            } catch (Exception var5) {
                ...
            }

        }
    }

那么是谁来调用这个register方法呢?这个我们后面再说。回到NacosDiscoveryAutoConfiguration类,这里面有几个注解需要关注,这几个注解定义了这个类执行的前提条件

@Configuration  #声明这是一个springboot配置类
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled#条件注解:只有NacosDiscoveryEnabledtrue时 这个类才生效
@ConditionalOnProperty(value = {"spring.cloud.service-registry.auto-registration.enabled"},
     				   matchIfMissing = true
                     )#和上面一样 只有配置文件中enabled为true时 这个类才生效 默认为true 如何使用其他框架例如dubbo进行服务注册 需要把这个设为false 要不然就会注册两个相同的服务
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class,
                     AutoServiceRegistrationAutoConfiguration.class})#声明需要在这两个bean创建之后进行加载
    
@ConditionalOnBean({AutoServiceRegistrationProperties.class})#容器中存在这个bean才会生效

问题3:Nacos服务注册源码解读

通过第二步的探究,我们锁定了register这个方法,那么是由谁来调用它的呢?

通过debug的方式 我们从控制台看到了这样的堆栈信息

在这里插入图片描述

通过堆栈信息可以清楚的看出来 它是从spring核心方法refresh方法中的finishRefresh方法进入的,它的大致链路就是refresh–>finishRefresh–>this.getLifecycleProcessor().onRefresh()–>startBeans(这个方法有一个while循环 当beanName是webServerStartStop时 走到下面链路)

–>((DefaultLifecycleProcessor.LifecycleGroup)phases.get(key)).start()

–>DefaultLifecycleProcessor.this.doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);

–>this.doStart(lifecycleBeans, dependency, autoStartupOnly);

–>bean.start()

–>this.applicationContext.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));

–>this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);

–>this.invokeListener(listener, event);

–this.doInvokeListener(listener, event);

–>listener.onApplicationEvent(event);

–>AbstractAutoServiceRegistration.onApplicationEvent.this.bind(event)

–this.start()

–this.register();

–this.serviceRegistry.register(this.getRegistration());

Nacos巧妙的运用springboot提供的事件订阅和发布机制,使得springboot应用在容器启动完成后第一时间调用register方法 将当前应用信息作为服务注册到nacos服务端

总结

首先springboot应用启动时会自动加载一个beanNamewebServerStartStop,这个bean对应的类是WebServerStartStopLifecycle,这个类又实现了SmartLifecycle这个接口,关于lifecycle接口的解释,借用网上的一段话

Lifecycle是Spring中最基础的生命周期接口,该接口定义了容器启动和停止的方法。方便开发者扩展自己的特定逻辑,比如启动和停止某些后台进程。Lifecycle常用来管理一个组件的启动和停止,可能会有这样的疑惑:开始和停止的逻辑写在一个bean的初始化方法和销毁方法中不可以了吗,为什么要实现个Lifecycle接口呢?这里说明一下,bean的初始化方法和销毁方法是Bean生命周期级别的;而Lifecycle是容器生命周期级别的。

它的意思就是 只有当容器启动和关闭的时候 ,springboot应用才会调用实现了这些接口的类

当我们context刷新成功之后会调用finishRefresh方法

protected void finishRefresh() {
    this.clearResourceCaches();
    this.initLifecycleProcessor();#在这里把所有实现了lifecycle的bean进行加载
    this.getLifecycleProcessor().onRefresh();#在这里把上面加载好的bean一一执行
    this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
    LiveBeansView.registerApplicationContext(this);
}

里面就有一个WebServerStartStopLifecycle这个bean,按照设定 会去调用这个bean的start方法

public void start() {
    this.webServer.start();
    this.running = true;
    this.applicationContext.publishEvent(
        new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}

这里关键的是最后的publishEvent方法,它会去发布一个事件,并将满足条件的监听器进行依次执行,从代码中可以看出 只要是ServletWebServerInitializedEvent相关的且实现了ApplicationListener的类 都会被执行,而ServletWebServerInitializedEvent又是WebServerInitializedEvent的子类,换句话讲 只要是WebServerInitializedEvent相关的类 都会被执行。

巧合的是AbstractAutoServiceRegistration这个类实现了ApplicationListener,并且入参泛型就是WebServerInitializedEvent,那么一定会执行到这个类中的方法。那么这个类是哪来的呢?回到最上面自动装配的那块,nacos自动装配的3个bean,其中最后一个beanNacosAutoServiceRegistration的父类就是AbstractAutoServiceRegistration

在执行满足条件的监听器方法时,会调用onApplicationEvent方法,然后到bind方法、start方法,最终在start方法中调用this.register()方法,调用的就是ServiceRegistryregister方法,而当前应用有且只有一个ServiceRegistry的实现类,就是NacosServiceRegistry,最终成功执行register方法,至此 nacos成功注册。

public abstract class AbstractAutoServiceRegistration<R extends Registration> implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
    private static final Log logger = LogFactory.getLog(AbstractAutoServiceRegistration.class);
    private final ServiceRegistry<R> serviceRegistry;
    private boolean autoStartup = true;
    private AtomicBoolean running = new AtomicBoolean(false);
    private int order = 0;
    private ApplicationContext context;
    private Environment environment;
    private AtomicInteger port = new AtomicInteger(0);
    private AutoServiceRegistrationProperties properties;

    protected void register() {
        this.serviceRegistry.register(this.getRegistration());
    }
    
    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);
            }

        }
        ........
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Cloud Alibaba 是一个基于 Spring Cloud 的开源框架,用于构建分布式应用程序。Nacos 是一个开源的服务发现、配置管理和服务管理平台,可以帮助开发人员更好地管理和维护分布式应用程序。 要搭建 Spring Cloud AlibabaNacos,需要按照以下步骤进行操作: 1. 下载和安装 JDK 和 Maven。 2. 创建一个 Spring Boot 项目,并添加 Spring Cloud AlibabaNacos 的依赖。 3. 在 Nacos 中创建一个命名空间和一个服务。 4. 在 Spring Boot 项目中配置 Nacos 的地址和服务信息。 5. 编写代码并运行应用程序。 具体的步骤可以参考 Spring Cloud AlibabaNacos 的官方文档,或者参考其他相关的教程和资料。 ### 回答2: SpringCloudAlibaba是一款非常流行的分布式系统框架,它提供了一个非常方便的方式来搭建高可扩展的分布式应用程序。当使用SpringCloudAlibaba构建分布式应用程序时,我们常常需要使用Nacos作为服务注册中心和配置中心。本文将介绍如何使用SpringCloudAlibaba来搭建Nacos。 首先,我们需要在本地安装Nacos。 步骤如下: 1. 下载Nacos:https://github.com/alibaba/nacos/releases 2. 解压下载的文件,进入bin目录 3. 运行startup.cmd(如果是在Linux系统下,运行startup.sh) 当我们成功启动Nacos后,我们需要在我们的应用程序中添加Nacos的依赖项。可以在pom.xml文件中添加如下代码: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> ``` 这个依赖项将会自动添加Spring Cloud Nacos Discovery的类和配置。 接下来,我们需要为我们的应用程序添加Nacos配置。可以在application.properties或者application.yml文件中添加如下代码: ``` spring.cloud.nacos.discovery.server-addr=localhost:8848 ``` 当我们的应用程序启动时,它将会自动注册Nacos。 最后,我们需要在我们的应用程序中使用Nacos作为配置中心。可以在配置文件中添加如下配置: ``` spring.cloud.nacos.config.server-addr=localhost:8848 ``` 这个配置项将会告诉我们的应用程序从Nacos中加载配置项。 当我们成功完成这些步骤后,我们的应用程序就已经成功地搭建了Nacos。现在我们可以使用Nacos作为服务注册中心和配置中心来管理我们的应用程序了。 ### 回答3: SpringCloudAlibaba是阿里巴巴团队推出的微服务框架,其中的nacos作为注册中心、配置中心以及服务发现组件,是使用SpringCloudAlibaba搭建微服务架构的重要组成部分。 下面是搭建nacos的详细步骤: 1.安装Java环境和Maven环境。在安装之前需要确保已经正确配置好Java和Maven的环境变量。 2.下载nacos的安装包。从nacos的官网中下载最新版的nacos安装包,解压缩到任意目录下。 3.启动nacos server。通过命令行进入nacos安装包所在的bin目录下,使用以下命令启动nacos: Linux/Unix/Mac: sh startup.sh –m standalone Windows: cmd startup.cmd 启动成功后通过访问http://localhost:8848/nacos/访问nacos的管理控制台,管理员账号和密码默认为nacos/nacos。 4.配置nacos客户端。在pom.xml文件中添加nacos的依赖: <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId> spring-cloud-starter-alibaba-nacos-discovery </artifactId> </dependency> 在配置文件application.yml中配置nacos信息: spring: cloud: nacos: discovery: server-addr: localhost:8848 # nacos服务的地址 application: name: service-provider # 微服务的名称 5.发布和发现微服务。使用@EnableDiscoveryClient注解启用服务发现功能,在微服务启动时自动注册nacos中,nacos管理控制台会显示注册的微服务信息。其他微服务可以通过调用nacos的API或者使用Ribbon等工具进行服务发现。 至此,使用SpringCloudAlibaba搭建nacos的过程就结束了。nacos提供的服务注册、配置管理和服务发现功能,为微服务的构建和部署提供了更方便、更高效、更可靠的方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值