天天看點

SpringCloudAlibaba的NacosClient自動注冊

概要

此篇部落格重點講述SpringCloudAlibaba的nacos的用戶端是怎麼在啟動的時候,把自己的服務注冊到注冊中心的。

綜述

  • SpringcloudAlibaba既然是SpringCloud項目,那麼它必定遵循SpringCloud定義的規範,該規範包括一些注冊服務,下線服務等。
  • SpringCloudAlibaba又是一個SpringBoot項目,那麼它肯定也遵循SpringBoot的規範,該規範包括自動裝配的spring.factories
  • SpringCloudAlibaba的啟動必然是使用SpringBoot的自動裝配的技術來實作它的自動啟動,相對來說主要是SpringBoot的流程

流程圖

可右鍵下載下傳

SpringCloudAlibaba的NacosClient自動注冊

步驟

一,maven倉庫位址

項目中引入的是這個jar包

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

二,檢視對應的jar包

SpringCloudAlibaba的NacosClient自動注冊

三,點開jar包,檢視jar包的自動配置檔案

SpringCloudAlibaba的NacosClient自動注冊

四,看這個檔案

發現了一堆的自動注冊的類。我們現在要看的代碼是服務自動注冊的流程,下列代碼最符合這個意思的是

NacosServiceRegistryAutoConfiguration

SpringCloudAlibaba的NacosClient自動注冊

五,配置類的代碼

  • com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration
    SpringCloudAlibaba的NacosClient自動注冊
  • 調用構造方法
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
			AutoServiceRegistrationProperties autoServiceRegistrationProperties,
			NacosRegistration registration) {
		super(serviceRegistry, autoServiceRegistrationProperties);
		this.registration = registration;
	}
           
  • 這個是調用父類的構造方法 org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
			AutoServiceRegistrationProperties properties) {
		this.serviceRegistry = serviceRegistry;
		this.properties = properties;
	}
           
  • 順便看看這個的關系圖
    SpringCloudAlibaba的NacosClient自動注冊
  • 有一個關鍵的實作,那就是ApplicationLIstener,它會在項目啟動的時候調用,我們看看這個方法
    SpringCloudAlibaba的NacosClient自動注冊
  • 它的父類實作了具體的方法,我們來看看方法具體

    監聽web容器啟動完成之後釋出的事件

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

           
  • 看bind方法
@Deprecated
	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();
	}


           
  • 看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);
		}

	}
           
  • 看register方法
/**
	 * Register the local service with the {@link ServiceRegistry}.
	 */
	protected void register() {
		this.serviceRegistry.register(getRegistration());
	}
           
  • com.alibaba.cloud.nacos.registry.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) {
			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);
		}
	}
           
  • 看注冊方法 com.alibaba.nacos.api.naming.NamingService#registerInstance
@Override
    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
        NamingUtils.checkInstanceIsLegal(instance);
        String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
        if (instance.isEphemeral()) {
            BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
            beatReactor.addBeatInfo(groupedServiceName, beatInfo);
        }
        serverProxy.registerService(groupedServiceName, groupName, instance);
    }
           
  • 看registerService方法
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);
        
    }
           

看到這裡就不用往下繼續看了,很明顯,這裡建構了一堆的參數。用來發送http網絡請求。伺服器會收到這個請求,把執行個體資料儲存下來