Nacos源码学习(5)— spring cloud集成nacos实现服务注册

nacos主要有两部分的功能:配置中心和注册中心,之前几篇文章讲了nacos作为配置中心的实现原理,这篇文章主要介绍下spring cloud如何集成nacos实现服务注册。

spring cloud服务注册实现原理

spring cloud服务注册具体逻辑是通过AbstractAutoServiceRegistration类实现的,它会监听WebServerInitializedEvent事件,当server初始化完成后,会自动注册服务到注册中心。spring cloud还停供了ServiceRegistry和Registration接口类,ServiceRegistry接口负责实现具体的注册逻辑,Registration接口是定义了注册的实例节点信息,包括实例ip、端口、服务id等信息。我们如果要自己实现服务注册功能,只需实现ServiceRegistry和Registration接口方法,并继承AbstractAutoServiceRegistration类实现里面的abstract方法即可。

先看一下AbstractAutoServiceRegistration的启动注册逻辑代码:

//监听WebServerInitializedEvent事件
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
   bind(event);
}

@Deprecated
public void bind(WebServerInitializedEvent event) {
   ApplicationContext context = event.getApplicationContext();
   if (context instanceof ConfigurableWebServerApplicationContext) {
       // 过滤掉management server
      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();
      //如果management不为空,也注册下
      if (shouldRegisterManagement()) {
         registerManagement();
      }
      //发布注册完成事件
      this.context.publishEvent(
            new InstanceRegisteredEvent<>(this, getConfiguration()));
      //标记为已注册成功      
      this.running.compareAndSet(false, true);
   }

}
protected void register() {
    //调用注册方法,serviceRegistry是在构造函数中传进来的
   this.serviceRegistry.register(getRegistration());
}
//子类只需实现此方法,把实例对象信息传递进来,即可实现服务注册功能
protected abstract R getRegistration();

nacos服务注册实现

nacos集成到spring cloud实现服务注册功能的逻辑跟上面讲到的方法是一样的,先是NacosAutoServiceRegistration继承了AbstractAutoServiceRegistration,然后NacosServiceRegistry和NacosRegistration分别实现了ServiceRegistry和Registration接口的方法。另外,NacosServiceRegistryAutoConfiguration类会把上述三个类自动实例化。这样,nacos就实现了应用启动服务时自动进行服务注册。

先看NacosAutoServiceRegistration的构造函数,它分别注入了NacosServiceRegistry和NacosRegistration类。

public NacosAutoServiceRegistration(ServiceRegistry serviceRegistry,
			AutoServiceRegistrationProperties autoServiceRegistrationProperties,
			NacosRegistration registration) {
		super(serviceRegistry, autoServiceRegistrationProperties);
		this.registration = registration;
	}

NacosAutoServiceRegistration的getRegistration方法就是返回的注入进来的NacosRegistration类:

@Override
protected NacosRegistration getRegistration() {
    //初始化实例的端口信息
   if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
      this.registration.setPort(this.getPort().get());
   }
   Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
   //返回NacosRegistration对象
   return this.registration;
}

再看一下NacosRegistration的实例信息,基本上都是从配置信息类里直接取的:

@Override
public String getServiceId() {
    //服务名
   return nacosDiscoveryProperties.getService();
}

@Override
public String getHost() {
   //实例ip
   return nacosDiscoveryProperties.getIp();
}

@Override
public int getPort() {
    //端口
   return nacosDiscoveryProperties.getPort();
}

@Override
public boolean isSecure() {
    //是否https
   return nacosDiscoveryProperties.isSecure();
}

@Override
public URI getUri() {
   return DefaultServiceInstance.getUri(this);
}

@Override
public Map getMetadata() {
    //获取元数据
   return nacosDiscoveryProperties.getMetadata();
}

NacosServiceRegistry是直接调用nacos服务端的服务注册和取消注册接口来实现的:

@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();
   //把NacosRegistration转化为nacos自有的Instance对象
   Instance instance = getNacosInstanceFromRegistration(registration);

   try {
       //调用nacos jdk的注册方法
      namingService.registerInstance(serviceId, group, instance);
      log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
            instance.getIp(), instance.getPort());
   }
   catch (Exception e) {
      if (nacosDiscoveryProperties.isFailFast()) {
         log.error("nacos registry, {} register failed...{},", serviceId,
               registration.toString(), e);
         rethrowRuntimeException(e);
      }
      else {
         log.warn("Failfast is false. {} register failed...{},", serviceId,
               registration.toString(), e);
      }
   }
}

@Override
public void deregister(Registration registration) {

   log.info("De-registering from Nacos Server now...");

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

   NamingService namingService = namingService();
   String serviceId = registration.getServiceId();
   String group = nacosDiscoveryProperties.getGroup();

   try {
       //调用nacos JDK的取消注册方法
      namingService.deregisterInstance(serviceId, group, registration.getHost(),
            registration.getPort(), nacosDiscoveryProperties.getClusterName());
   }
   catch (Exception e) {
      log.error("ERR_NACOS_DEREGISTER, de-register failed...{},",
            registration.toString(), e);
   }

   log.info("De-registration finished.");
}

你可能感兴趣的:(spring,cloud,学习,spring)