服务启动何时触发 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) {
	//获取 ApplicationContext
	ApplicationContext context = event.getApplicationContext();
	//判断服务的 namespace
	if (!(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() {
    }

    @Bean
    public 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 的监听机制在我们平时写代码中几乎用不到,但是在框架源码中还是大量使用了的。

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

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值