文章目录

  • 一. 问题背景
  • 二. 前言
  • 三. 资源准备
  • 四. 原理
  • 4.1 快速开始构建spring应用的nacos步骤
  • 4.2 问题分析
  • 4.3 Spring Cloud Alibaba Nacos的自动服务注册大概原理
  • 4.4 源码分析Spring Cloud Commons模块的服务注册原理
  • 4.4.1 引入依赖
  • 4.4.2 服务注册的核心方法
  • 4.4.3 服务注册的调用关系
  • 4.4.4 更底层的原理
  • 4.5 利用事件监听机制完成自动服务注册的原理(重要)
  • 五. 课外知识
  • 5.1 Spring应用重构成微服务的方案
  • 5.2 WebServerInitializerEvent事件在哪里发布的?
  • 六. 总结


一. 问题背景

想要对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官方手册,可见如下:

vue nacos注册中心 数据 nacos注册原理_vue nacos注册中心 数据


解释: 从上面可以大概看到,spring应用将服务注册到nacos中,大概就是发一个请求,某个controller会处理该请求,然后controller中会调用某些service方法做处理,然后注册服务。

4.2 问题分析

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

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

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

如下图所示:

vue nacos注册中心 数据 nacos注册原理_ide_02

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官方手册看到的注册服务的步骤,可以大概知道如下:

vue nacos注册中心 数据 nacos注册原理_Cloud_03

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 利用事件监听机制完成自动服务注册的原理(重要)

vue nacos注册中心 数据 nacos注册原理_vue nacos注册中心 数据_04


vue nacos注册中心 数据 nacos注册原理_spring_05

vue nacos注册中心 数据 nacos注册原理_vue nacos注册中心 数据_06

五. 课外知识

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

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

5.2 WebServerInitializerEvent事件在哪里发布的?

根据SpringBoot版本的不同,发布的地方也可能不同。

vue nacos注册中心 数据 nacos注册原理_vue nacos注册中心 数据_07

六. 总结

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