服务注册入口

无论是将服务注册到哪种服务注册中心,服务注册的时机都是在AbstractApplicationContext#finishRefresh()方法中;即Spring容器加载完成、Web服务启动之后;

从SpringCloud规范来看,Spring-cloud-common包定义了一套服务注册、发现的规范;服务注册逻辑在ServiceRegistry类中;

package org.springframework.cloud.client.serviceregistry;

/**
 * Contract to register and deregister instances with a Service Registry.
 *
 * @param <R> registration meta data
 * @author Spencer Gibb
 * @since 1.2.0
 */
public interface ServiceRegistry<R extends Registration> {

 /**
  * Registers the registration. A registration typically has information about an
  * instance, such as its hostname and port.
  * @param registration registration meta data
  */
 void register(R registration);

 /**
  * Deregisters the registration.
  * @param registration registration meta data
  */
 void deregister(R registration);

 /**
  * Closes the ServiceRegistry. This is a lifecycle method.
  */
 void close();

 /**
  * Sets the status of the registration. The status values are determined by the
  * individual implementations.
  * @param registration The registration to update.
  * @param status The status to set.
  * @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
  */
 void setStatus(R registration, String status);

 /**
  * Gets the status of a particular registration.
  * @param registration The registration to query.
  * @param <T> The type of the status.
  * @return The status of the registration.
  * @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
  */
 <T> T getStatus(R registration);

}

1、Eureka

从SpringBoot自动装配来看,spring-cloud-netflix-eureka-client包中有一个自动装配类EurekaClientAutoConfiguration

其中使用@Bean注入一个类EurekaAutoServiceRegistration,它实现了SmartLifecycle接口



springboot dubbo nacos注册自定义命名空间问题_java

当Spring容器初始化完成之后会执行所有SmartLifecycle#start()方法,链路如下:



springboot dubbo nacos注册自定义命名空间问题_eureka_02

springboot dubbo nacos注册自定义命名空间问题_spring cloud_03

进而走到EurekaAutoServiceRegistration#start()方法中;



springboot dubbo nacos注册自定义命名空间问题_eureka_04

其中的serviceRegistry.register()负责服务注册到服务注册中⼼Eureka。Eureka中EurekaServiceRegistry类实现了ServiceRegistry接口,因此Eureka服务注册的入口为EurekaServiceRegistry#register()方法;

@Override
public void register(EurekaRegistration reg) {
 maybeInitializeClient(reg);

 if (log.isInfoEnabled()) {
  log.info("Registering application "
    + reg.getApplicationInfoManager().getInfo().getAppName()
    + " with eureka with status "
    + reg.getInstanceConfig().getInitialStatus());
 }

 reg.getApplicationInfoManager()
   .setInstanceStatus(reg.getInstanceConfig().getInitialStatus());

 reg.getHealthCheckHandler().ifAvailable(healthCheckHandler -> reg
   .getEurekaClient().registerHealthCheck(healthCheckHandler));
}

2、Nacos

从SpringBoot自动装配来看,spring-cloud-alibaba-nacos-discovery 包中有一个自动装配类NacosServiceRegistryAutoConfigurationNacosServiceRegistryAutoConfiguration中会使用@Bean注解装配NacosAutoServiceRegistration类;

public class NacosServiceRegistryAutoConfiguration {

 @Bean
 public NacosServiceRegistry nacosServiceRegistry(
   NacosDiscoveryProperties nacosDiscoveryProperties) {
  return new NacosServiceRegistry(nacosDiscoveryProperties);
 }

 @Bean
 @ConditionalOnBean(AutoServiceRegistrationProperties.class)
 public NacosAutoServiceRegistration nacosAutoServiceRegistration(
   NacosServiceRegistry registry,
   AutoServiceRegistrationProperties autoServiceRegistrationProperties,
   NacosRegistration registration) {
  return new NacosAutoServiceRegistration(registry,
    autoServiceRegistrationProperties, registration);
 }

    ....
}

NacosAutoServiceRegistration间接实现了ApplicationListener接⼝;



springboot dubbo nacos注册自定义命名空间问题_java_05

springboot dubbo nacos注册自定义命名空间问题_云原生_06

其会监听Web服务初始化完成事件WebServerInitializedEvent

在Spring生命周期中,上下文刷新完成阶段,即finishRefresh()方法中会执行所有SmartLifecycle#start()方法;

WebServerStartStopLifecycle实现了SmartLifecycle接口,进而走到WebServerStartStopLifecycle#start()方法,其中会发布Servlet服务初始化完成事件ServletWebServerInitializedEvent



springboot dubbo nacos注册自定义命名空间问题_spring cloud_07

ServletWebServerInitializedEventWebServerInitializedEvent的子类。所以监听WebServerInitializedEventApplicationListener可以监听到ServletWebServerInitializedEvent



springboot dubbo nacos注册自定义命名空间问题_云原生_08

NacosAutoServiceRegistration的父类AbstractAutoServiceRegistration中基于ApplicationListener#onApplicationEvent()监听到事件;



springboot dubbo nacos注册自定义命名空间问题_云原生_09

然后走到NacosAutoServiceRegistration#register()方法开始做服务注册;



springboot dubbo nacos注册自定义命名空间问题_eureka_10

最终会走到ServiceRegistry接口的register(R registration)⽅法将服务注册到注册中⼼。Nacos中NacosServiceRegistry类实现了ServiceRegistry接口。



springboot dubbo nacos注册自定义命名空间问题_eureka_11

总结

从Eureka和Nacos做服务注册的入口来看,有两种方式让我们去做服务注册。

  • 基于扩展SmartLifecycle接口实现,在Spring上下文刷新完毕之后会执行SmartLifecycle#start()方法;
  • 基于监听Spring事件WebServerInitializedEvent,在ApplicationListener#onApplicationContext()方法中写逻辑;

基于Spring事件机制的特性,可以做异步服务注册处理。

本质上也是利用了SmartLifecycle接口,区别在于使用了SpringBoot web模块的WebServerStartStopLifecycle

此外,还要遵循spring-cloud-common定义的规范,自定义服务注册的入口类一定要是ServiceRegistry接口的实现类。

作者:秃秃爱健身