Nacos源码客户端系列第4篇服务什么时候开始注册

目录

加载自动装配类

服务注册触发时机

服务注册核心流程

 核心类(NacosAutoServiceRegistration)解析

 核心类(NacosServiceRegistry)解析 

总结


本篇开始我们正式讲解客户端源码

本篇学习目标:通过本篇学习我们要知道 nacos 服务注册是如何集成到springcloud, 什么时候触发服务注册的,服务注册的主流程是什么样的,服务注册又有哪些核心类。

加载自动装配类

spring boot 在启动后扫描【spring-cloud-alibaba-nacos-discovery】jar包 下的spring.factory文件。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration,\
  org.springframework.cloud.alibaba.nacos.ribbon.RibbonNacosAutoConfiguration,\
  org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
  org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration


其中负责服务注册的自动化配置类是配置文件中的第一个 org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration

该类会创建NacosServiceRegistry

NacosRegistration

NacosAutoServiceRegistration 3个Bean 

public class 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);
    }

}

NacosRegistration:封装服务注册的基本信息 包括服务的serviceId、 服务的Ip 和 port 、cluster(所属集群名) 、weight(实例的权重)、isSecure、uri(http[https]://ip:port/)、metaData(实例扩展数据或者元数据)、除了namingService是手动创建的, 其他的这些属性基本上都是通过项目的属性文件配置的 

NacosAutoServiceRegistration继承自AbstractAutoServiceRegistration : 服务启动后父类会监听web server 初始化事件从而触发当前服务实例的注册流程

NacosServiceRegistry 负责服务的注册和下线功能

服务注册触发时机

NacosAutoServiceRegistration 的父类AbstractAutoServiceRegistration监听了WebServer 初始化事件,当监听到web server 初始化事件时执行 bind(WebServerInitializedEvent event) 方法

服务启动事件触发方法:bind(WebServerInitializedEvent event):

public class AbstractAutoServiceRegistration{

  //web服务器在初始化时唤醒该方法
  public void bind(WebServerInitializedEvent event) {
		ApplicationContext context = event.getApplicationContext();
        ...
        //如果当前的端口号是0就用服务启动的端口比如8080
		this.port.compareAndSet(0, event.getWebServer().getPort());
        //调用启动发放
		this.start();
	}


   public void start() {

		// 如果服务如果已注册过则跳过
		if (!this.running.get()) {

           //发布注册前事件
			this.context.publishEvent(
					new InstancePreRegisteredEvent(this, getRegistration()));

            // 服务注册入口
			register();

			if (shouldRegisterManagement()) {
				registerManagement();
			}

           //发布注册后事件
			this.context.publishEvent(
					new InstanceRegisteredEvent<>(this, getConfiguration()));

           //设置服务注册状态为已注册
			this.running.compareAndSet(false, true);
		}

	}

   // 服务注册接着调用NacosServiceRegistry 的注册方法
      protected void register() {
		this.serviceRegistry.register(getRegistration());
	   }
}

WebServerInitializedEvent—>Web服务器已初始化事件.当Web服务器初始化完毕后会通知此事件,上面的代码很简单根据一个cas变量判断当前服务是否完成服务的注册

另外在服务注册前后会发布2个事件提供扩展能力。 

通过代码可以看出服务注册内部调用的serviceRegistry.registry方法.

这里的serviceRegistry 就是我们上面自动装配类里面的NacosServiceRegistry类,提供了服务注册和下线的统一操作入口,这也是springcloud提供的接口,nacos实现了自己的NacosRegistration,下面的内容会讲解具体代码。

服务注册核心流程

 

 核心类(NacosAutoServiceRegistration)解析

//服务启动后该类监听web server 初始化事件触发 服务注册流程
public class NacosAutoServiceRegistration
		extends AbstractAutoServiceRegistration<Registration> {

    //包装了服务注册基本信息[注册信息其属性大部分来源于配置文件]   
	private NacosRegistration registration;

	public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
			AutoServiceRegistrationProperties autoServiceRegistrationProperties,
			NacosRegistration registration) {
		super(serviceRegistry, autoServiceRegistrationProperties);
		this.registration = registration;
	}

   
	@Deprecated
	public void setPort(int port) {
		getPort().set(port);
	}
    
   //如果属性文件配置的端口不合法重新设置端口
	@Override
	protected NacosRegistration getRegistration() {
		if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
			this.registration.setPort(this.getPort().get());
		}
		Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
		return this.registration;
	}

    ...
    
    //调用父方法实现注册
	@Override
	protected void register() {
		if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
			log.debug("Registration disabled.");
			return;
		}
		if (this.registration.getPort() < 0) {
			this.registration.setPort(getPort().get());
		}
		super.register();
	}

	...
   
    // 用户在配置文件中配置的属性
	@Override
	protected Object getConfiguration() {
		return this.registration.getNacosDiscoveryProperties();
	}

    //是否可以启用服务注册[纯消费者可以设置该属性为false]
	@Override
	protected boolean isEnabled() {
		return this.registration.getNacosDiscoveryProperties().isRegisterEnabled();
	}
    
    //首先从[spring.cloud.nacos.discovery.service]获取appName, 如果没有获取到则从 
    //        [spring.application.name]属性获取  
	@Override
	@SuppressWarnings("deprecation")
	protected String getAppName() {
		String appName = registration.getNacosDiscoveryProperties().getService();
		return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
	}

}

 核心类(NacosServiceRegistry)解析 

//实现ServiceRegistry接口的服务注册 spring正是通过该接口为nacos的注册服务提供了可能
public class NacosServiceRegistry implements ServiceRegistry<Registration> {

    ...
    //nacos 配置属性
	private final NacosDiscoveryProperties nacosDiscoveryProperties;

    //可以理解为 nacos 客户端统一的服务管理器
	private final NamingService namingService;
    
    ...

	@Override
	public void register(Registration registration) {

		if (StringUtils.isEmpty(registration.getServiceId())) {
			log.warn("No service to register for nacos client...");
			return;
		}

        //如果没有配置属性【spring.cloud.nacos.discovery.service】
        //就使用【spring.application.name】
		String serviceId = registration.getServiceId();
        //创建要注册的实例
		Instance instance = new Instance();
		instance.setIp(registration.getHost());
		instance.setPort(registration.getPort());
		instance.setWeight(nacosDiscoveryProperties.getWeight());
		instance.setClusterName(nacosDiscoveryProperties.getClusterName());
        //扩展数据
		instance.setMetadata(registration.getMetadata());

		...
        //调用namingService注册服务
			namingService.registerInstance(serviceId, instance);
			log.info("nacos registry, {} {}:{} register finished", serviceId,
					instance.getIp(), instance.getPort());
		...
	}

    //服务下线功能
	@Override
	public void deregister(Registration registration) {

		...

		NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
		String serviceId = registration.getServiceId();

		...
			namingService.deregisterInstance(serviceId, registration.getHost(),
					registration.getPort(), nacosDiscoveryProperties.getClusterName());
		...
	}

	@Override
	public void close() {

	}

	@Override
	public void setStatus(Registration registration, String status) {
		// nacos doesn't support set status of a particular registration.
	}

	@Override
	public <T> T getStatus(Registration registration) {
		// nacos doesn't support query status of a particular registration.
		return null;
	}

}

上面的serverId 一般不用手动配置默认会匀服务名,也可以通过【spring.cloud.nacos.discovery.service】属性配置。

通过代码可以看出首先通过 NacosRegistration  和  nacosDiscoveryProperties[配置文件相关属性] 构建一个Instance 对象 然后调用下一章要详细讲解的 NacosNamingService 统一发起注册和下线功能

注意: NacosRegistration 负责包装 配置属性文件里面的属性 。比spring cloud的 Registration  接口提供了更多的属性比如 registerWeight、Cluster、isRegisterEnabled等。因此你可以理解了 为什么 weight 性和  clusterName 要从 nacosDiscoveryProperties 去获而不是通过 registration 去获取 

instance.setWeight(nacosDiscoveryProperties.getWeight());
instance.setClusterName(nacosDiscoveryProperties.getClusterName());

欢迎关注公众号【奇点架构】

Instance: 注册的实例信息 字段如下类图:

  • Instance:有几个重要的属性分别是: ip、端口、权重(不能小于1)、集群名、扩展信息    
  • nacos: 的数据模型从上到下 namespace -> service -> group -> cluster -> instance        
  • namespace : 待注册实例所属的空间一般可以表示不同的环境 默认是PUBLIC       
  • service:注册服务名                                                                                                          
  • group: 待注册实例所属分组 默认是:DEFAULT_GROUP                                             
  • cluster: 待注册实例所属集群 不是必须的

总结

 Nacos 之所以可以作为独立的第三方注册中心集成到spring cloud 我觉得有下面几点原因

1、spring cloud提供下面3个接口或抽象类作为扩展点

    class AbstractAutoServiceRegistration<R extends Registration>

    Interface ServiceRegistry

    Interface Registration

所以nacos的第一个启动的自动装配类【NacosDiscoveryAutoConfiguration】就是 创建基于上面3个接口的实现类。

2、spring boog 通过spring.factories文件配置帮助提供了服务的扩展能力

本文我们讲解了3个核心类 NacosAutoServiceRegistration 和 NacosServiceRegistry

NacosRegistration类么有专门讲解因为它注意是对nacos 配置属性的封装,并没有太多的业务功能。

后面接下来的注册流程就完全进入到了nacos自己的实现中。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值