Nacos解读:服务发现与Spring Cloud的整合
source link: https://blog.darkness463.top/2019/03/22/Nacos-Naming-With-Spring-Cloud/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前面介绍了Nacos服务发现(Naming)的客户端的实现,了解到客户端会协助我们与Nacos服务端通信,进行注册、获取服务、心跳等操作。但在实际使用过程中,很少会直接去使用Nacos提供的客户端,官方也提供了与Spring Cloud集成的方式,我们来一起看看服务发现(Naming)的客户端是如何与Spring Cloud结合的。
使用简介
引入依赖
在 dependencyManagement
中添加如下配置。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>0.2.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
引入 Nacos Discovery Starter。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
配置Nacos服务端地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
开启服务发现
通过 @EnableDiscoveryClient
注解开启服务注册与发现功能。
Ribbon
Nacos Discovery Starter默认集成了Ribbon,通过在RestTemplate Bean上增加 @LoadBalanced
注解或者使用FeignClient即可实现负载均衡。
实现原理
背景知识
自动装配是Spring Boot的一大特性。一般来说,Spring Boot或第三方库会提供一些以 Enable
开头的注解来供使用者配置开启某些功能,例如 @EnableWebMvc
、 @EnableScheduling
以及上面的 @EnableDiscoveryClient
等。
实现的原理是借助 @Import
注解。 @Import
注解可导入的内容有三种:
@Configuration ImportSelector ImportBeanDefinitionRegistrar
更多详细信息如果感兴趣可以自行了解一下。
@EnableDiscoveryClient
与Eureka一样,Nacos同样利用 @EnableDiscoveryClient
开启服务注册与发现,降低了从Eureka迁移到Nacos的成本。
@Import(EnableDiscoveryClientImportSelector.class) public @interface EnableDiscoveryClient { boolean autoRegister() default true; }
@EnableDiscoveryClient
导入的类为 EnableDiscoveryClientImportSelector
,继承自 SpringFactoryImportSelector
, SpringFactoryImportSelector
会读取 META-INF/spring.factories
,加载其中配置的类。
spring-cloud-alibaba-nacos-discovery
中有Nacos Discovery的 spring.factories
文件,其内容如下。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.alibaba.nacos.NacosDiscoveryAutoConfiguration,\ org.springframework.cloud.alibaba.nacos.ribbon.RibbonNacosAutoConfiguration,\ org.springframework.cloud.alibaba.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration org.springframework.cloud.client.discovery.EnableDiscoveryClient=\ org.springframework.cloud.alibaba.nacos.NacosDiscoveryClientAutoConfiguration
因此,启用自动装配后,会加载 NacosDiscoveryAutoConfiguration
、 RibbonNacosAutoConfiguration
、 NacosDiscoveryEndpointAutoConfiguration
这三个类,添加 @EnableDiscoveryClient
后将加载 NacosDiscoveryClientAutoConfiguration
。
NacosDiscoveryClientAutoConfiguration
NacosDiscoveryClientAutoConfiguration会注册DiscoveryClient和NacosDiscoveryProperties两个Bean,当然有一些条件,只有当前不存在DiscoveryClient的Bean并且满足 ConditionalOnNacosDiscoveryEnabled
时才会注册。
ConditionalOnNacosDiscoveryEnabled
在 spring.cloud.nacos.discovery.enabled
配置为true时满足条件,默认为true。换句话来说,我们可以把这个设置为false来停掉Nacos Discovery。
NacosDiscoveryProperties还额外有不存在该Bean时才注册的条件,我们也可以在代码里注册NacosDiscoveryProperties Bean来改变官方对它的实现。
@Configuration @ConditionalOnMissingBean(DiscoveryClient.class) @ConditionalOnNacosDiscoveryEnabled @EnableConfigurationProperties public class NacosDiscoveryClientAutoConfiguration { @Bean public DiscoveryClient nacosDiscoveryClient() { return new NacosDiscoveryClient(); } @Bean @ConditionalOnMissingBean public NacosDiscoveryProperties nacosProperties() { return new NacosDiscoveryProperties(); } }
NacosDiscoveryProperties
NacosDiscoveryProperties的配置加载自 application.properties
,前缀为 spring.cloud.nacos.discovery
,现把可配置项总结如下。
NacosDiscoveryClient
Nacos的DiscoveryClient的实现类是NacosDiscoveryClient,利用Nacos Client对外提供的API实现了DiscoveryClient的获取实例列表和获取所有Service名的方法。
@Override public List<ServiceInstance> getInstances(String serviceId) { try { List<Instance> instances = discoveryProperties.namingServiceInstance() .selectInstances(serviceId, true); return hostToServiceInstanceList(instances, serviceId); } catch (Exception e) { throw new RuntimeException( "Can not get hosts from nacos server. serviceId: " + serviceId, e); } } @Override public List<String> getServices() { try { ListView<String> services = discoveryProperties.namingServiceInstance() .getServicesOfServer(1, Integer.MAX_VALUE); return services.getData(); } catch (Exception e) { LOGGER.error("get service name from nacos server fail,", e); return Collections.emptyList(); } }
其他自动装配的配置类
NacosDiscoveryAutoConfiguration
NacosDiscoveryAutoConfiguration用于把当前服务向Nacos服务端注册,会注册3个Bean,分别为NacosServiceRegistry、NacosRegistration、NacosAutoServiceRegistration。如果不想自动向Nacos服务端注册,可通过 spring.cloud.service-registry.auto-registration.enabled
配置关闭。
NacosRegistration即保存了当前实例的IP、端口等信息,用于向Nacos服务端注册,这些信息都是从上面提到的NacosDiscoveryProperties中获取的。
NacosServiceRegistry实现了具体的注册、注销逻辑,即利用NacosRegistration的信息,通过Nacos Client的API向Nacos服务端注册。
NacosAutoServiceRegistration继承了AbstractAutoServiceRegistration,用于串联NacosRegistration和NacosServiceRegistry进行注册。
RibbonNacosAutoConfiguration
RibbonNacosAutoConfiguration用于集成Ribbon,在 ribbon.nacos.enabled
配置为true(默认为true)且classpath下有Ribbon相关类时会进行配置,利用 @RibbonClients
导入 NacosRibbonClientConfiguration
,通过继承Ribbon的 AbstractServerList
的 NacosServerList
类,利用Nacos Client的相关API,实现Ribbon的客户端负载均衡。
具体可参照Ribbon的相关文档。
@Configuration @EnableConfigurationProperties @ConditionalOnBean(SpringClientFactory.class) @ConditionalOnRibbonNacos @AutoConfigureAfter(RibbonAutoConfiguration.class) @RibbonClients(defaultConfiguration = NacosRibbonClientConfiguration.class) public class RibbonNacosAutoConfiguration { }
NacosDiscoveryEndpointAutoConfiguration
这个类在开启了Endpoint(Spring Boot的Endpoint,并非上面提到的配置Nacos服务端的Endpoint)的情况下,会将 NacosDiscoveryEndpoint
注册为Bean,并暴露一个名为 nacos-discovery
的Endpoint,实际调用的是 NamingService#getSubscribeServices
方法,会返回服务信息。
总结
借助Nacos Discovery Starter,我们无需改代码就可从Eureka迁移到Nacos,实现了服务注册发现、Ribbon负载均衡,从实现上讲,Spring/Spring Boot提供的整体框架还是相当优雅的。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK