26

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

 5 years ago
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 ,继承自 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提供的整体框架还是相当优雅的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK