Naocs

NacosServiceRegistryAutoConfiguration : 服务注册入口类
NacosAutoServiceRegistration : 自动注册服务流程
NacosServiceRegistry : 服务注册实现类
NacosRegistration : 服务注册实体,包含注册服务所需要的信息
NacosNamingMaintainService : 服务治理类(service)
NacosNamingService : 服务实例(instance)
NamingProxy : 网络代理类
NacosRegistrationCustomizer : 2020.9新版本中加入,用于向NacosRegistration中注入配置
CacheData : 维护配置项和其下注册的所有监听器的实例
BeatInfo : 心跳包信息


NacosDiscoveryAutoConfiguration: 服务发现入口
NacosDiscoveryProperties : 服务注册,发现相关的配置类
NacosServiceDiscovery : 服务发现的实现过程,为NacosDiscovery模块提供nacos上的service和instance信息.
NacosDiscoveryClientConfiguration : 
NacosServiceInstance : 服务实例(instance)实体信息,只在服务发现模块使用
NacosDiscoveryClient : 服务信息提供类,提供getInstances和getServices方法
EventDispatcher : 当instances信息更新时,给监听者们发布事件消息.
NacosWatch : 监听EventDispatcher发布的消息,并同步到NacosDiscoveryProperties的元数据中

配置管理

服务注册

  • 服务注册的入口类是NacosServiceRegistryAutoConfiguration,这里定义了三个重要的bean :NacosServiceRegistry,NacosRegistration,NacosAutoServiceRegistration
  • 如果项目集成了spring-cloud-starter-alibaba-nacos-discovery,服务启动后默认是自动注册的。如果想看自动注册的过程,可以从NacosAutoServiceRegistration开始着手
  • NacosServiceRegistry : 提供了register()方法给NacosAutoServiceRegistration进行服务注册.依赖NacosNamingService
  • NacosRegistration : 服务注册实体,包含注册服务所需要的信息.提供了customize()方法给用户注入配置.
  • NacosRegistrationCustomizer : 方便用户自定义 NacosRegistrationCustomizer 实现,向 NacosRegistration 中注入配置
  • NacosDiscoveryProperties : 服务注册相关的配置类,读取application.yml里以spring.cloud.nacos.discovery为前缀的配置项
  • NacosNamingMaintainService : 服务治理类(service),包含在nacos上创建服务,查询服务,删除服务等功能.通过调用关系可以发现该类是在NacosServiceRegistry的setStatus()方法(控制instance上线或下线)中被创建的,也就是nacos的服务是懒加载的,当需要对实例进行上线下线时,才会去获取对应的service,如果service不存在才会创建.而setStauts()是在ServiceRegistryEndpoint中被调用(spring cloud的类)
  • NacosNamingService : 服务实例(instance)管理,包括把实例注册到服务上,订阅/取消订阅服务等功能.
  • NamingProxy : 发起http请求的方法,基本上对于nacos服务器的所有网络请求都需要调用这里的callServer()

服务注册主流程 :

	/**
	 *NacosAutoServiceRegistration
	 * Register the local service with the {@link ServiceRegistry}.
	 */
	protected void register() {
		this.serviceRegistry.register(getRegistration());
	}

	/**
	 * NacosServiceRegistry
	 */
	public void register(Registration registration) {
		namingService.registerInstance(serviceId, group, instance);
	}


	/**
	 * NacosNamingService
	 */
    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
		serverProxy.registerService(groupedServiceName, groupName, instance);       }

NacosAutoServiceRegistration中有两个事件监听器.

一个是onNacosDiscoveryInfoChangedEvent().当监听到NacosDiscoveryProperties的配置信息改变时就会重新注册.

	@EventListener
	public void onNacosDiscoveryInfoChangedEvent(NacosDiscoveryInfoChangedEvent event) {
		restart();
	}

	private void restart() {
		this.stop();
		this.start();
	}

另一个是在父类AbstractAutoServiceRegistration中定义的事件监听器,这是因为实现了ApplicationListener接口(需要先了解spring boot的事件监听机制).直接看onApplicationEvent()即可.

	@Override
	public void onApplicationEvent(WebServerInitializedEvent event) {
		bind(event);
	}

	@Deprecated
	public void bind(WebServerInitializedEvent event) {
		ApplicationContext context = event.getApplicationContext();
		if (context instanceof ConfigurableWebServerApplicationContext) {
			if ("management".equals(((ConfigurableWebServerApplicationContext) context)
					.getServerNamespace())) {
				return;
			}
		}
		this.port.compareAndSet(0, event.getWebServer().getPort());
		this.start();
	}

	public void start() {
		if (!isEnabled()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Discovery Lifecycle disabled. Not starting");
			}
			return;
		}

		// only initialize if nonSecurePort is greater than 0 and it isn't already running
		// because of containerPortInitializer below
		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);
		}

	}

可以看到,服务注册是在WebServer启动完毕之后调用的.

此外,spring boot和nacos大量使用了**事件发布(ApplicationContext.publishEvent()) -> 事件监听(@EventListener) ) **的模式来控制各流程的执行顺序,这个特性需要好好掌握.

Spring 在实现的时候,通过设计模式(装饰),实现流程,又把关键部分丢给开发自己实现,提高了拓展性,然后巧妙的结合了观察者模式(变种),在合适的时间注册服务.

服务发现

  • NacosDiscoveryAutoConfiguration : 服务发现的入口,包含NacosDiscoveryPropertiesNacosServiceDiscovery两个bean.该类上有两个注解 : @ConditionalOnDiscoveryEnabled和@ConditionalOnNacosDiscoveryEnabled(都引入了@ConditionalOnProperty),也就是当配置项"spring.cloud.discovery.enabled"和"spring.cloud.nacos.discovery.enabled"都为true时才进行自动装配.由于这里设置了matchIfMissing = true,缺省值是true,所以默认是自动装配,不需要填写相关配置.也就是引入了nacos的相关包之后服务发现就自动开启了,不需要在Application类加上@EnableDiscoveryClient注解.
  • @EnableDiscoveryClient原先是用于自动启用服务注册功能,以便其他服务发现本服务.在Spring的官方文档中已经声明**@EnableDiscoveryClient不是必须的了(从Spring Cloud Edgware开始),所有DiscoveryClient类型的bean都会自动注册**.
  • NacosDiscoveryProperties : 是nacos的配置类,虽然从名字上看只属于服务发现这一模块,但实际上服务发现的配置也是由该类提供.负责读取并提供"spring.cloud.nacos.discovery"前缀的配置.overrideFromEnv()方法负责注入配置属性.此外,enrichNacosDiscoveryProperties()允许用户在配置文件里自定义额外的nacos配置.
  • @PostConstruct : 上面这个类的init()方法里面用到,作用是当该类的依赖注入完成后,且该类被投入使用前,执行包含该注解的方法.作用类似于构造方法/构造代码块,目的是完成该类的初始化工作,之后才能服务于其他类.
  • NacosServiceInstance : 服务实例(instance)实体信息,只在服务发现模块使用.
  • NacosServiceDiscovery : 服务发现实现类,包含服务发现的过程,为NacosDiscovery模块提供nacos上的service和instance信息,并实现instance向serviceInstance的转换.依赖NacosServiceManager提供的namingService.这里需要注意的是虽然可以直接从NacosServiceManager得到服务信息,但是用户直接依赖的是NacosServiceDiscovery而不是NacosServiceManager,这样的设计的依据可能是单一职责原则,NacosServiceManager负责管理service,而对外提供服务的职责由NacosServiceDiscovery承担.
  • NacosDiscoveryClientConfiguration : 加载NacosServiceDiscovery和NacosWatch两个bean.
  • NacosDiscoveryClient : 服务信息提供类,仅对外提供NacosServiceDiscovery的getInstances和getServices方法(职责划分得很细嘛).也就是说nacos组件外想获取服务和实例信息的话都应该通过这个类获取.
  • NacosWatch: 负责监听EventDispatcher中发布的instances更新事件,并同步到NacosDiscoveryProperties的元数据中.

Feign

FeignClientsRegistrar : 注册实现类
@EnableFeignClients
@EnableDiscoveryClient
@FeignClient