@EnableDiscoveryClient與Nacos的服務注冊與拉取


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



環境:
SpringBoot: 2.3.5
SpringCloud: Hoxton.SR8
SpringCloudAlibaba: 2.2.3


配置信息:

@SpringBootApplication
//autoRegiste屬性值默認為true可以不配置此屬性
@EnableDiscoveryClient(autoRegister = true)
public class NacosApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(NacosApplication.class, args);
    }
    
}
spring:
  application:
    name: nacosTest
  cloud:
    nacos:
      discovery:
        enabled: true(默認為true,可以不配置此屬性)
        server-addr: 192.168.1.10:8848
        username: nacos
        password: nacos

配置的作用:

nacos.discovery.enabled: 開啟服務的注冊與發現功能;
注冊成功后可以在nacos的web端界面看到服務的相關信息
image
同時,具備拉取服務信息的功能, discoveryClient.getInstances()方法可以返回服務的詳細配置信息

@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/client")
public List<ServiceInstance> client() {
    return discoveryClient.getInstances("服務名稱");
}

@EnableDiscoveryClient(autoRegister = true); 開啟服務自動注冊功能,項目啟動后能在nacos的web端界面看到服務的相關信息,並且具備拉取服務信息的功能(前提是nacos.discovery.enabled不為false)
@EnableDiscoveryClient(autoRegister = false); 關閉服務自動注冊功能, 項目啟動后nacos的web端界面沒有此項目的信息,但是依然具備拉取服務信息的功能(前提是nacos.discovery.enabled不為false)


實現邏輯:

@EnableDiscoveryClient

打開@EnableDiscoveryClient注解(代碼里只保留了重點)

@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的源碼

Nacos:

找到nacos的spring.factories文件,這是配置自動配置類的地方,文件路徑:
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

既然有BootstrapConfiguration,那就先看最后一行的NacosDiscoveryClientConfigServiceBootstrapConfiguration

//刪減了部分代碼,便於閱讀
@ImportAutoConfiguration({NacosDiscoveryClientConfiguration.class})
public class NacosDiscoveryClientConfigServiceBootstrapConfiguration {

}

繼續進入NacosDiscoveryClientConfiguration

//刪減了部分代碼,便於閱讀
//spring.cloud.nacos.discovery.enabled=true時,此配置類才會加載
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureAfter(NacosDiscoveryAutoConfiguration.class)
public class NacosDiscoveryClientConfiguration {
	@Bean
	public DiscoveryClient nacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
		return new NacosDiscoveryClient(nacosServiceDiscovery);
	}
}

此配置類注入了一個bean: NacosDiscoveryClient, 這個類實現了DiscoveryClient接口, 我們上邊的測試用例
discoveryClient.getInstances("服務名稱"), 調用的getInstances方法,實際上就是調用了Nacos官方提供的NacosDiscoveryClient重寫的getInstances方法,
至此,Nacos的的服務拉取搞明白了: 無論是否配置@EnableDiscoveryClient,只要spring.cloud.nacos.discovery.enabled不設置為false,服務就具有拉取注冊中心信息的功能

那服務注冊功能呢? 返回spring.factories打開第五行的類: NacosServiceRegistryAutoConfiguration
服務自動注冊邏輯:

@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(autoRegister=false),配置nacos.discovery.enable=true 不具有服務注冊功能,具有拉取服務信息功能
配置@EnableDiscoveryClient(autoRegister=false),配置nacos.discovery.enable=false 服務注冊與拉取服務信息功能都不具備

最后:

才疏學淺,難免有疏漏或者錯誤的地方,希望各位不吝指教


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM