@EnableDiscoveryClient與Nacos自動註冊

Java挖坑工程師發表於2021-07-07

 

前一陣看到有篇部落格說cloud從Edgware版本開始,可以不加@EnableDiscoveryClient註解,只要配置好註冊中心的相關配置即可自動開啟服務註冊功能,比較好奇其中的原理,研究了一番特意記錄下來

 

環境:

  SpringBoot:  2.3.5

  SpringCloud: Hoxton.SR8

  SpringCloudAlibaba: 2.2.3

 

 

先看一下@EnableDiscoveryClient註解,只有一個屬性:autoRegister, 預設為true

@SpringBootApplication
@EnableDiscoveryClient(autoRegister = true)
public class NacosApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(NacosApplication.class, args);
    }
    
}

  

內部資訊(程式碼裡只保留了重點)

@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
	boolean autoRegister() default true;
}

  

EnableDiscoveryClientImportSelector

@Override
public String[] selectImports(AnnotationMetadata metadata) {
    String[] imports = super.selectImports(metadata);

    AnnotationAttributes attributes = AnnotationAttributes.fromMap(
        metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
	//獲取@EnableDiscoveryClient的autoRegister屬性
    boolean autoRegister = attributes.getBoolean("autoRegister");
	//開啟自動註冊的話,將AutoServiceRegistrationConfiguration類的全限定名返回,會被spring載入到bean容器
    if (autoRegister) {
        List<String> importsList = new ArrayList<>(Arrays.asList(imports));
        importsList.add(
            "org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
        imports = importsList.toArray(new String[0]);
    }
    //關閉自動註冊的話,將***.auto-registration.enabled設定為false,放入環境屬性中(其他地方會用到)
    else {
        Environment env = getEnvironment();
        if (ConfigurableEnvironment.class.isInstance(env)) {
            ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env;
            LinkedHashMap<String, Object> map = new LinkedHashMap<>();
            map.put("spring.cloud.service-registry.auto-registration.enabled", false);
            MapPropertySource propertySource = new MapPropertySource(
                "springCloudDiscoveryClient", map);
            configEnv.getPropertySources().addLast(propertySource);
        }

    }

    return imports;
}

  

AutoServiceRegistrationConfiguration是實現自動註冊的入口,具體的邏輯在由註冊中心實現(如Nacos\Eureka...)

//當**.registration.enabled屬性為true時,此配置類會被載入
//spring-cloud-commons.jar包內的spring-configuration-metadata.json定義了此屬性預設為true
//即: 不配置@EnableDiscoveryClient或者配置@EnableDiscoveryClient設定autoRegister為true時
//AutoServiceRegistrationConfiguration會被載入,當@EnableDiscoveryClient的autoRegister
//為false時,此配置類不會被載入
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
		matchIfMissing = true)
public class AutoServiceRegistrationConfiguration {

}

  

Nacos實現邏輯

配置:
spring: application: name: nacosTest cloud: nacos: discovery: enabled: true(預設為true,可以不配置) server-addr: 192.168.1.10 port: 8848 username: nacos password: nacos

  

spring-cloud-starter-alibaba-nacos-discovery.jar/META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
  com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration,\
  com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
  com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
  com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
  com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
  com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
  com.alibaba.cloud.nacos.NacosServiceAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
  com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration

  

開啟NacosServiceRegistryAutoConfiguration.java, 內部實現了服務自動註冊邏輯

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
//確保spring.cloud.nacos.discovery.enabled為true(開啟nacos的服務註冊與發現功能)
@ConditionalOnNacosDiscoveryEnabled
//預設為true,只有開啟了@EnableDiscoveryClient註解,並且配置autoRegister為false時,
//此屬性值才為false
@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);
	}

}

  

最後測試:

配置

是否成功註冊到註冊中心

不配置@EnableDiscoveryClient,不配置nacos.discovery.enable

不配置@EnableDiscoveryClient,配置nacos.discovery.enable=false

配置@EnableDiscoveryClient,配置nacos.discovery.enable=true

配置@EnableDiscoveryClient,配置nacos.discovery.enable=false

配置@EnableDiscoveryClient(autoRegister=false),配置nacos.discovery.enable=true

配置@EnableDiscoveryClient(autoRegister=false),配置nacos.discovery.enable=false

相關文章