Day1——Nacos自动服务注册原理(一)

一. 问题背景

想要对spring应用做扩展,达到spring应用可以SpringBoot应用那样自动注册服务到nacos的功能。

参考自: 【java进阶课程】玩转spring cloud alibaba易如反掌,从入门到精通nacos

二. 前言

  1. nacos官方文档可以去nacos.io或者spring.io中的alibaba模块学习。视频中的讲师推荐去spring.io官网参考(因为nacos.io有小小的毛病),但是由于国内无法访问github.io域名的页面,只能去nacos.io参考了。

  2. 本文从源码级别讲解,因此需要使用idea启动nacos,笔者启动的时候遇到了挺多坑,如何使用idea单机启动nacos请看源码启动单机运行nacos

  3. 本文旨在讲原理,不必过分在某些细节纠结,对原理了解个大概就好了。后面还会再写更细致更深入的博客,一切细节根据自己所用的springboot版本等。

三. 资源准备

  1. nacos源码:前往nacos的github页面下载,用来启动nacos的
  2. springboot工程:前往gitee页面下载,用来研究nacos自动服务注册的源码

四. 原理

4.1 快速开始构建spring应用的nacos步骤

前往nacos-spring官方手册,可见如下:
在这里插入图片描述
解释: 从上面可以大概看到,spring应用将服务注册到nacos中,大概就是发一个请求,某个controller会处理该请求,然后controller中会调用某些service方法做处理,然后注册服务。

4.2 问题分析

从上面也可以看到,spring应用是不能自动注册服务到nacos中的,需要手动发一个请求去注册,因此我们要对spring做扩展,把spring应用自动注册到nacos里面。

那么到底如何实现?我们可以参考spring cloud alibaba nacos是怎么做自动注册的。

4.3 Spring Cloud Alibaba Nacos的自动服务注册大概原理

如下图所示:
在这里插入图片描述

4.4 源码分析Spring Cloud Commons模块的服务注册原理

4.4.1 引入依赖

新建一个SpringBoot应用并引入以下nacos-discovery依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

在加了@SpringBootApplication的主类上加@EnableDiscoveryClient,就可以在SpringBoot应用程序启动的时候进行自动服务注册到nacos。

4.4.2 服务注册的核心方法

切入点是位于org.springframework.cloud.client包下的ServiceRegistry接口的register()方法,如下:


package org.springframework.cloud.client.serviceregistry;

public interface ServiceRegistry<R extends Registration> {
    
    
    void register(R registration);

    //...此处省略其他代码
}

Nacos对该接口方法的实现是com.alibaba.cloud.nacos.registry包下的NacosServiceRegistryregister()方法。 方法如下:

@Override
	public void register(Registration registration) {
    
    

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

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

		Instance instance = getNacosInstanceFromRegistration(registration);

		try {
    
    
			namingService.registerInstance(serviceId, group, instance);
			log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
					instance.getIp(), instance.getPort());
		}
		catch (Exception e) {
    
    
			log.error("nacos registry, {} register failed...{},", serviceId,
					registration.toString(), e);
			// rethrow a RuntimeException if the registration is failed.
			// issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
			rethrowRuntimeException(e);
		}
	}

解释:以上这个代码块就是nacos做自动服务注册的核心代码。

结合前面nacos.io官方手册看到的注册服务的步骤,可以大概知道如下:
在这里插入图片描述

4.4.3 服务注册的调用关系

逆向 查找调用关系(用idea的find usage找找,但是我的不行)

NacosServiceRegistry#register()
<-ServiceRegistry#register()
<-AbstractAutoServiceRegistration()#register()
<-AbstractAutoServiceRegistration#start()
<-AbstractAutoServiceRegistration#bind()
<-AbstractAutoServiceRegistration#onApplicationEvent()

解释:最终的核心方法register()是被ServiceRegistry中的register()调用的;而ServiceRegistryregister()方法是被AbstractAutoServiceRegistrationregister()方法调用的,以此类推

总结:由此可知,客户端能完成自动服务注册的功能是因为一启动的时候调用了AbstractAutoServiceRegistration#onApplicationEvent()

4.4.4 更底层的原理

是用了Spring的 事件监听机制(观察者模型,事件编程模型)。(Spring用了很多模式,比如有代理设计模式)

4.5 利用事件监听机制完成自动服务注册的原理(重要)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

五. 课外知识

5.1 Spring应用重构成微服务的方案

  1. 先将spring应用拆分成各个模块,比如订单模块,登录模块,权限模块等。
  2. 然后再将spring cloud等组件添加进去。切忌直接spring应用重构成spring cloud 微服务,因为spring cloud组件太多,不容易调bug

5.2 WebServerInitializerEvent事件在哪里发布的?

根据SpringBoot版本的不同,发布的地方也可能不同。
在这里插入图片描述

六. 总结

  1. 首先必须要知道spring cloud做了服务注册的接口标准,而nacos作为产品,是对spring cloud做的接口进行整合实现的。一个是做标准,另一个是做实现。必须要理清这点。
  2. spring cloud项目的commons模块定义了服务注册的接口标准
  3. nacos的自动服务注册就是按着spring cloud commons的服务注册的接口标准来实现的

猜你喜欢

转载自blog.csdn.net/qq_40634846/article/details/111462383