SpringBoot整合Nacos服務註冊加載原理二

2024年2月6日 23点热度 0人点赞

前言

上文我們說到SpringBoot整合Nacos在服務啟動時候會往容器中註入
NacosAutoServiceRegistration對象,它是實現註冊的關鍵組件,下面我們重點分析一下它的源碼。

源碼分析


NacosAutoServiceRegistration的繼承關系圖如下所示:

NacosAutoServiceRegistration繼承關系圖

由類圖可以看出它繼承了
AbstractAutoServiceRegistration類,而
AbstractAutoServiceRegistration又實現了ApplicationListener接口,可以看出它是一個監聽的類,它會監聽什麼事件那?讓我們看看它的onApplicationEvent的定義:

@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
   bind(event);
}

可以看出它監聽WebServerInitializedEvent事件,這個事件是在什麼時候發佈的那?

這個類是SpringBoot下面定義的類,來看看它的代碼:

package org.springframework.boot.web.context;
import org.springframework.boot.web.server.WebServer;
import org.springframework.context.ApplicationEvent;
@SuppressWarnings("serial")
public abstract class WebServerInitializedEvent extends ApplicationEvent {
   protected WebServerInitializedEvent(WebServer webServer) {
      super(webServer);
   }
   public WebServer getWebServer() {
      return getSource();
   }
   public abstract WebServerApplicationContext getApplicationContext();
   @Override
   public WebServer getSource() {
      return (WebServer) super.getSource();
   }
}

給它的解釋是在容器刷新以後並且是WebServer準備好了以後會發佈這個事件。

在SpringBoot啟動階段最終會調用
AbstractApplicationContext的finishRefresh方法,在該方法內部會循環調用所有實現了SmartLifecycle接口的bean並調用它的start方法,其中有一個類實現了SmartLifecycle接口,它是
WebServerStartStopLifecycle,該類的start方法代碼如下:

@Override
public void start() {
   this.webServer.start();
   this.running = true;
   this.applicationContext
         .publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}

可以看出它發佈了一個
ServletWebServerInitializedEvent事件,該事件正好是WebServerInitializedEvent的子類,知道這一點就好辦了,那麼我們的
AbstractAutoServiceRegistration就會監聽到這個事件,調用bind方法,最終會調用到start方法,然後調用到register方法,該方法的代碼如下:

protected void register() {
   this.serviceRegistry.register(getRegistration());
}

這個serviceRegistry的類型是ServiceRegistry,它的實現類是NacosServiceRegistry,就是我們第一篇文章說的,它已經註入到容器中了,getRegistration獲取到的對象是NacosRegistration,這個對象同樣也註入到容器中了,我們重點來看NacosServiceRegistry的register方法:

@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) {
      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);
      }
   }
}

這段代碼邏輯是從NacosServiceManager中獲取NamingService,這個對象相當於是和服務器的一個長連接,把實例註冊到服務器端的,這塊的邏輯我在Nacos單服務的時候已經分析過了,感興趣的朋友可以移駕Nacos源碼分析(二)NacosNamingService初始化以及註冊過程

到此為止這個註冊就算完成了,邏輯比較簡單,註冊的具體邏輯都在Nacos那塊,感興趣的朋友可以到我Nacos源碼合集專題那塊去看一下具體是怎麼註冊到服務器端的。

總結:

註冊流程可以分為以下幾個步驟:

1.SpringBoot完成容器的刷新以後發佈WebServerInitializedEvent事件。


2.NacosAutoServiceRegistration監聽這個事件處理註冊邏輯。

3.封裝配置文件中配置的信息為Instance對象,調用Nacos底層邏輯進行服務註冊。

下一節我將分析Nacos和Ribbon的源碼,還請大傢持續關註,好了,我是愛好編程的程序員老徐,如果喜歡我的文章請點贊關註,我們下期見。