Nacos源码解析(一)-服务自动注册

springcloud alibaba 开启服务自动注册使用注解:

@EnableDiscoveryClient

结合到spring-cloud-starter-alibaba-nacos-discovery依赖,查看META-INF中spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

  com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\

  com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration,\

  com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
  //NacosServiceRegistryAutoConfiguration为Nacos服务注册配置类
  com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\

  com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\

  com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\

  com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\

  com.alibaba.cloud.nacos.NacosServiceAutoConfiguration

org.springframework.cloud.bootstrap.BootstrapConfiguration=\

  com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration

看到NacosServiceRegistryAutoConfiguration,查看源码:

@Configuration(proxyBeanMethods = false)

@EnableConfigurationProperties

@ConditionalOnNacosDiscoveryEnabled

@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",

      matchIfMissing = true)
//AutoConfigureAfter 顾名思义,需要的前置配置类

@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,

      AutoServiceRegistrationAutoConfiguration.class,

      NacosDiscoveryAutoConfiguration.class })

public class NacosServiceRegistryAutoConfiguration {



   @Bean

   public NacosServiceRegistry nacosServiceRegistry(

         NacosDiscoveryProperties nacosDiscoveryProperties) {

      return new NacosServiceRegistry(nacosDiscoveryProperties);

   }



   @Bean

   @ConditionalOnBean(AutoServiceRegistrationProperties.class)

   public NacosRegistration nacosRegistration(

         ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,

         NacosDiscoveryProperties nacosDiscoveryProperties,

         ApplicationContext context) {

      return new NacosRegistration(registrationCustomizers.getIfAvailable(),

            nacosDiscoveryProperties, context);

   }



   @Bean

   @ConditionalOnBean(AutoServiceRegistrationProperties.class)

   public NacosAutoServiceRegistration nacosAutoServiceRegistration(

         NacosServiceRegistry registry,

         AutoServiceRegistrationProperties autoServiceRegistrationProperties,

         NacosRegistration registration) {

      return new NacosAutoServiceRegistration(registry,

            autoServiceRegistrationProperties, registration);

   }



}

备注:

NacosServiceRegistryAutoConfiguration中有一条注解:

@AutoConfigureAfter

包含三个类:

AutoServiceRegistrationConfiguration.class,

AutoServiceRegistrationAutoConfiguration.class,

NacosDiscoveryAutoConfiguration.class

注:其中AutoServiceRegistrationAutoConfiguration是通过@EnableDiscoveryClient注解注入到spring中,可以看出,如果要开启NacosServiceRegitryAutoConfiguration,必须先加载配置AutoSeviceRegistrationAutoConfiguration。所以,这就是为什么需要使用@EnableDiscoveryClient注解,来开启服务的自动注册。

在NacosServiceRegistryAutoConfiguration中配置了三个BEAN

1.NacosServiceRegistry

2.NacosRegistration

3.NacosAutoServiceRegistration

1.NacosServiceRegistry  可以理解为Nacos服务注册器,实现了ServiceRegistry,泛型为Registration(Registration可以理解为注册信息封装类)。包含registry、deRegistry方法,由此可知,该类是完成服务的注册、注销功能,这两个方式均为接口方法的实现

public class NacosServiceRegistry implements ServiceRegistry<Registration>

//注册

public void register(Registration registration)

//注销

public void deregister(Registration registration)

2.NacosRegistration 该类为注册信息的封装类

NacosRegistration实现了Registration、ServiceInstance根据1中NacosServiceRegistry实现接口的泛型类型以及registrer/deregistrer方法的入参,可以大致了解到,需要将NacosRegistration信息封装后,传递到NacosServiceRegistry中,完成服务的注册、注销

NacosRegistration中init方法中使用@PostConstruct注解,主要是在类完成构建后,获取服务配置信息的收集 

public class NacosRegistration implements Registration, ServiceInstance



@PostConstruct

public void init()

3.NacosAutoServiceRegistration Nacos自动服务注册 主要是完成服务的自动注册

public class NacosAutoServiceRegistration

      extends AbstractAutoServiceRegistration<Registration>



public abstract class AbstractAutoServiceRegistration<R extends Registration>

      implements AutoServiceRegistration, ApplicationContextAware,

      ApplicationListener<WebServerInitializedEvent>

NacosAutoServiceRegistration 继承 AbstractAutoServiceRegistration , AbstractAutoServiceRegistration 实现了 ApplicationListener<WebServerInitializedEvent> 的onApplicationEvent方法

1.WebServerInitializedEvent事件后,执行onApplicationEvent方法

public void onApplicationEvent(WebServerInitializedEvent event) {

   bind(event);

}

2.进入bind方法

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();

}

3.进入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);

   }



}

4.进入register方法

protected void register() {

   this.serviceRegistry.register(getRegistration());

}

由于NacosAutoServiceRegistration配置了NacosRegistry,此处的调用直接到NacosServiceRegistry的register方法

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);

   }

}

此处需要注意两行代码:

1.NamingService namingService = namingService();

获取namingService

2.namingService.registerInstance(serviceId, group, instance);

使用namingservice注册实例

获取namingService

1.通过nacosServiceManager获取namingService

private NamingService namingService() {

   return nacosServiceManager

         .getNamingService(nacosDiscoveryProperties.getNacosProperties());

}

调用栈:   

NacosServiceManager

    getNamingService

        ->buildNamingService

          ->createNewNamingService

            ->createNamingService

              ->NamingFactory.createNamingService(properties);

从NamingFactory正式从nacos-discovery依赖到nacos-api进入初始化NamingService的流程

后续调用NamingsService完成服务注册。

下一章:解读NamingService初始化


版权声明:本文为yizefeng7241原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。