nacos注册中心自动配置原理

609 阅读2分钟

版本说明

<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>2.2.0.RELEASE</version>

1、nacos服务注册客户端使用

1.1导入依赖

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

1.2启动类上加注解@EnableDiscoveryClient

@EnableDiscoveryClient
@SpringBootApplication
public class OrderServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}

3、注册中心服务端的配置信息

2、spring.factories文件

springboot应用在启动时会加载类路径下META-INF/spring.factories文件,将key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的value加载到spring容器中。 在spring-cloud-alibaba-nacos-discovery模块类路径下META-INF/spring.factories文件中,导入了 NacosDiscoveryAutoConfiguration、NacosServiceRegistryAutoConfiguration、RibbonNacosAutoConfiguration等配置类

2.1 NacosDiscoveryAutoConfiguration 读取properties配置文件

public class NacosDiscoveryAutoConfiguration {


   //注入spring.cloud.nacos.discovery配置
   @Bean
   @ConditionalOnMissingBean
   public NacosDiscoveryProperties nacosProperties() {
      return new NacosDiscoveryProperties();
   }

   //nacos服务发现客户端
   @Bean
   @ConditionalOnMissingBean
   public NacosServiceDiscovery nacosServiceDiscovery(
         NacosDiscoveryProperties discoveryProperties) {
      return new NacosServiceDiscovery(discoveryProperties);
   }

}

2.2 nacos服务注册客户端启动流程

NacosServiceRegistryAutoConfiguration

public class NacosServiceRegistryAutoConfiguration {



   //nacos服务注册
   @Bean
   public NacosServiceRegistry nacosServiceRegistry(
         NacosDiscoveryProperties nacosDiscoveryProperties) {
      return new NacosServiceRegistry(nacosDiscoveryProperties);
   }

   //封装服务注册配置信息和上下文
   @Bean
   @ConditionalOnBean(AutoServiceRegistrationProperties.class)
   public NacosRegistration nacosRegistration(
         NacosDiscoveryProperties nacosDiscoveryProperties,
         ApplicationContext context) {
      return new NacosRegistration(nacosDiscoveryProperties, context);
   }



   //构造器传入的就是上面注入的NacosServiceRegistry
   //整合springcloud common,监听WebServerInitializedEvent事件
   @Bean
   @ConditionalOnBean(AutoServiceRegistrationProperties.class)
   public NacosAutoServiceRegistration nacosAutoServiceRegistration(
         NacosServiceRegistry registry,
         AutoServiceRegistrationProperties autoServiceRegistrationProperties,
         NacosRegistration registration) {
      return new NacosAutoServiceRegistration(registry,
            autoServiceRegistrationProperties, registration);
   }

}

NacosAutoServiceRegistration

public abstract class AbstractAutoServiceRegistration<R extends Registration> implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {

    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.bind(event);
    }
    
    public void bind(WebServerInitializedEvent event) {
        ApplicationContext context = event.getApplicationContext();
        if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
            this.port.compareAndSet(0, event.getWebServer().getPort());
            //调用
            this.start();
        }
    }
    
    public void start() {
        if (!this.isEnabled()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Discovery Lifecycle disabled. Not starting");
            }

        } else {
            if (!this.running.get()) {
                this.context.publishEvent(new InstancePreRegisteredEvent(this, this.getRegistration()));
                //注册 NacosAutoServiceRegistration重写了register方法
                this.register();
                if (this.shouldRegisterManagement()) {
                    this.registerManagement();
                }

                this.context.publishEvent(new InstanceRegisteredEvent(this, this.getConfiguration()));
                this.running.compareAndSet(false, true);
            }

        }
    }
}

//父类AbstractAutoServiceRegistration实现了ApplicationListener接口,监听WebServerInitializedEvent
public class NacosAutoServiceRegistration
      extends AbstractAutoServiceRegistration<Registration> {
      
    //服务注册
    @Override
    protected void register() {
       if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
          log.debug("Registration disabled.");
          return;
       }
       if (this.registration.getPort() < 0) {
          this.registration.setPort(getPort().get());
       }
       //最后调用到NacosServiceRegistry.register
       super.register();
    }

}

public class NacosServiceRegistry implements ServiceRegistry<Registration> {
    
    //服务注册和服务发现的顶层接口
    private final NamingService namingService;
    
    public void register(Registration registration) {

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

       //service
       String serviceId = registration.getServiceId();
       //group
       String group = nacosDiscoveryProperties.getGroup();

       Instance instance = getNacosInstanceFromRegistration(registration);

       try {
          //服务注册 进入到nacos的源码
          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);
          rethrowRuntimeException(e);
       }
    }


}

2.3 nacos整合ribbon

RibbonNacosAutoConfiguration是nacos整合服务注册客户端整合ribbon的配置类,指定了RibbonClients的配置类为NacosRibbonClientConfiguration

@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = NacosRibbonClientConfiguration.class)
public class RibbonNacosAutoConfiguration {

}
public class NacosRibbonClientConfiguration {

   @Autowired
   private PropertiesFactory propertiesFactory;


   //实现ribbon的ServerList组件,ServerList用来获取服务的地址信息
   @Bean
   @ConditionalOnMissingBean
   public ServerList<?> ribbonServerList(IClientConfig config,
         NacosDiscoveryProperties nacosDiscoveryProperties) {
      if (this.propertiesFactory.isSet(ServerList.class, config.getClientName())) {
         ServerList serverList = this.propertiesFactory.get(ServerList.class, config,
               config.getClientName());
         return serverList;
      }
      //基于NamingService做服务发现
      NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties);
      serverList.initWithNiwsConfig(config);
      return serverList;
   }
}

注意:nacos注册中心自动配置,客户端只是将自己注册到注册中心,服务发现需要有服务调用的时候,借助于ribbon的ServerList组件,实现基于nacos的服务发现(从注册中心获取服务信息)