Nacos-Client注册源码分析

  • Post author:
  • Post category:其他


1. 注册流程

源码目录下client模块下的一个测试类,模仿客户端服务注册流程

NamingTest.java

@Ignore
public class NamingTest {
    
    @Test
    public void testServiceList() throws Exception {
        
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
        properties.put(PropertyKeyConst.USERNAME, "nacos");
        properties.put(PropertyKeyConst.PASSWORD, "nacos");

        //客户端构建一个服务实例
        Instance instance = new Instance();
        instance.setIp("1.1.1.1");
        instance.setPort(800);
        instance.setWeight(2);

        //instance默认参数
        //默认间隔心跳,默认5秒
        //getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL, Constants.DEFAULT_HEART_BEAT_INTERVAL)
        //默认心跳超时时间,默认15秒
        //getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,  Constants.DEFAULT_HEART_BEAT_TIMEOUT);
        //收不到心跳默认剔除时间,默认30秒
        //getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT,  Constants.DEFAULT_IP_DELETE_TIMEOUT);
        //实例ID的默认生成器,也可以自己设置一个
        //getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.DEFAULT_INSTANCE_ID_GENERATOR);

        //注册元数据信息
        Map<String, String> map = new HashMap<String, String>();
        map.put("netType", "external");
        map.put("version", "2.0");
        instance.setMetadata(map);

        //创建一个连接Nacos-Server的服务,Nacos命名服务对外提供的统一接口。
        //NamingService包含各种接口,如注册,注销,查询,订阅事件等
        //实际上调用了NacosNamingService的构造方法
        NamingService namingService = NacosFactory.createNamingService(properties);
        //将实例注册到nacos-server的注册中心
        //先检查设置的各种时间是否争抢(心跳间隔<超时时间<剔除时间),然后注册,瞬时实例用RPC注册,否则使用http方式注册
        //2.0后默认为瞬时对象
        namingService.registerInstance("nacos.test.1", instance);

        ThreadUtils.sleep(5000L);
        
        List<Instance> list = namingService.getAllInstances("nacos.test.1");
        
        System.out.println(list);
        
        ThreadUtils.sleep(30000L);

        //        ExpressionSelector expressionSelector = new ExpressionSelector();
        //        expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
        //        ListView<String> serviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
        
    }
}

2. 注册结果

3. 流程图说明

4. SpringBoot客户端注册流程

  1. 引入pom之后
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. SpringBoot启动会自动装配spring.factories下的类

  2. 自动装配类(NacosServiceRegistryAutoConfiguration)

  3. NacosServiceRegistryAutoConfiguration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
      matchIfMissing = true)
@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);
   }

}
  1. 关键类NacosAutoServiceRegistration自动创建该Bean,

    该类的父类AbstractAutoServiceRegistration实现了ApplicationContextAware 会在SpringBean创建完成后自动调用

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() {
      ...
      //触发注册
      this.register();
      ...
}

protected void register() {
    //服务注册(NacosServiceRegistry)
    this.serviceRegistry.register(this.getRegistration());
}

  1. NacosServiceRegistry注册具体实现类
//注册实现核心代码
@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);
  }
}
  1. NamingProxy
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
    
    NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
            instance);
    
    final Map<String, String> params = new HashMap<String, String>(16);
    params.put(CommonParams.NAMESPACE_ID, namespaceId);
    params.put(CommonParams.SERVICE_NAME, serviceName);
    params.put(CommonParams.GROUP_NAME, groupName);
    params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
    params.put("ip", instance.getIp());
    params.put("port", String.valueOf(instance.getPort()));
    params.put("weight", String.valueOf(instance.getWeight()));
    params.put("enable", String.valueOf(instance.isEnabled()));
    params.put("healthy", String.valueOf(instance.isHealthy()));
    params.put("ephemeral", String.valueOf(instance.isEphemeral()));
    params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
    
    reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
    
}

Nacos注册实例API


Open API 指南



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