转载

Nacos解读:服务发现与Spring Cloud的整合

前面介绍了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 ,继承自 SpringFactoryImportSelectorSpringFactoryImportSelector 会读取 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

因此,启用自动装配后,会加载 NacosDiscoveryAutoConfigurationRibbonNacosAutoConfigurationNacosDiscoveryEndpointAutoConfiguration 这三个类,添加 @EnableDiscoveryClient 后将加载 NacosDiscoveryClientAutoConfiguration

NacosDiscoveryClientAutoConfiguration

NacosDiscoveryClientAutoConfiguration会注册DiscoveryClient和NacosDiscoveryProperties两个Bean,当然有一些条件,只有当前不存在DiscoveryClient的Bean并且满足 ConditionalOnNacosDiscoveryEnabled 时才会注册。

ConditionalOnNacosDiscoveryEnabledspring.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 ,现把可配置项总结如下。

Key 默认值 说明
server-addr Nacos Server地址
service ${spring.application.name} 给当前的服务命名
weight 1 权重,1~100,数值越大,权重越大
network-interface 网卡名,默认取第一块网卡的地址
ip 注册的IP地址,默认自动探测
port -1 注册的端口,默认自动探测
namespace 命名空间
access-key 阿里云云账号名
secret-key 阿里云云账号密码
metadata 元数据信息
log-name 日志文件名
enpoint 接入点方式获取服务端地址
namingLoadCacheAtStart false 启动时是否加载本地保存的信息
registerEnabled true 是否注册当前应用
secure false 是否为https

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的 AbstractServerListNacosServerList 类,利用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提供的整体框架还是相当优雅的。

原文  https://blog.darkness463.top/2019/03/22/Nacos-Naming-With-Spring-Cloud/
正文到此结束
Loading...