天天看点

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网络请求。服务器会收到这个请求,把实例数据保存下来