本文主要对SpringCloudAlibaba组件Nacos实现服务注册发现和作为配置中心使用进行简单总结,其中SpringBoot使用的2.4.5
版本,SpringCloud使用的2020.0.2
版本,SpringCloudAlibaba使用的2021.1
版本。
Spring Cloud Alibaba为分布式应用开发提供了一个一站式解决方案。它包含了开发分布式应用服务的必需组件,使开发者能轻松使用Spring Cloud进行分布式应用服务开发。通过Spring Cloud Alibaba,只需添加一些注解和少量配置,就可以将Spring Cloud应用接入阿里分布式应用解决方案,并通过阿里中间件来迅速搭建分布式应用系统。
Spring Cloud Alibaba常用组件:
Nacos致力于发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,用于快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos使地构建、交付和管理微服务平台变得更容易。 Nacos是构建以“服务”为中心的现代应用架构的服务基础设施。
Nacos关键特性:
Nacos依赖Java环境来运行。如果是从代码开始构建并运行Nacos,还需要为此配置Maven环境,请确保是在以下版本环境中安装使用:
从Github上下载源码方式:
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin
从最新稳定版本下载编译后压缩包nacos-server-$version.zip
的方式:
unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
Linux/Unix/Mac启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
如果使用的是ubuntu系统,或者运行脚本报错提示[[
符号找不到,可尝试如下运行:
bash startup.sh -m standalone
Windows启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
Nacos下载的2.0.1版本,在Windows运行成功后,可以访问http://localhost:8848/nacos查看Nacos的管理页面,默认账号密码都是nacos:
Linux/Unix/Mac关闭命令:
sh shutdown.sh
Windows关闭命令:
shutdown.cmd
或者双击shutdown.cmd
运行文件。
通过Maven新建一个名为spring-cloud-alibaba-nacos-discovery-provider
的项目作为服务提供者(服务生产者),一个名为spring-cloud-alibaba-nacos-discovery-consumer
的项目作为服务消费者。
编写pom.xml
文件:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.rtxtitanvgroupId>
<artifactId>spring-cloud-alibaba-nacos-discovery-providerartifactId>
<version>1.0.0version>
<packaging>jarpackaging>
<name>spring-cloud-alibaba-nacos-discovery-providername>
<description>nacos discovery providerdescription>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-boot.version>2.4.5spring-boot.version>
<spring-cloud.version>2020.0.2spring-cloud.version>
<spring-cloud-alibaba.version>2021.1spring-cloud-alibaba.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring-boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
Nacos Discovery Starter可以将服务自动注册到Nacos服务端并且能够动态感知和刷新某个服务实例的服务列表。除此之外,Nacos Discovery Starter也将服务实例自身的一些元数据信息-例如host,port,健康检查URL,主页等-注册到Nacos。
主启动类:
package com.rtxtitanv;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.NacosDiscoveryProviderApplication
* @description 主启动类
* @date 2021/4/30 17:57
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosDiscoveryProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoveryProviderApplication.class, args);
}
}
@EnableDiscoveryClient
:开启SpringCloud服务注册于发现
编写配置文件,在application.yml
中进行如下配置:
server:
port: ${PORT:8090}
spring:
application:
name: nacos-discovery-provider
cloud:
nacos:
discovery:
# nacos服务器地址
server-addr: 127.0.0.1:8848
如果不想使用Nacos实现服务注册与发现,可以将
spring.cloud.nacos.discovery.enabled
设置为false
。
创建测试用的Controller:
package com.rtxtitanv.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.ProviderController
* @description ProviderController
* @date 2021/4/30 18:01
*/
@RestController
public class ProviderController {
@Value("${server.port}")
private String port;
@Value("${spring.cloud.client.ip-address}")
private String ip;
@GetMapping("/home")
public String home() {
return "ip:" + ip + ",port:" + port;
}
}
编写pom.xml
文件:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.rtxtitanvgroupId>
<artifactId>spring-cloud-alibaba-nacos-discovery-consumerartifactId>
<version>1.0.0version>
<packaging>jarpackaging>
<name>spring-cloud-alibaba-nacos-discovery-consumername>
<description>nacos discovery consumerdescription>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-boot.version>2.4.5spring-boot.version>
<spring-cloud.version>2020.0.2spring-cloud.version>
<spring-cloud-alibaba.version>2021.1spring-cloud-alibaba.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring-boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
注意:由于SpringCloud 2020版本已经移除了Ribbon,需要引入
spring-cloud-starter-loadbalancer
依赖来代替Ribbon实现负载均衡。
主启动类:
package com.rtxtitanv;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.NacosDiscoveryConsumerApplication
* @description 主启动类
* @date 2021/4/30 17:57
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosDiscoveryConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoveryConsumerApplication.class, args);
}
}
编写配置文件,在application.yml
中进行如下配置:
server:
port: ${PORT:8080}
spring:
application:
name: nacos-discovery-consumer
cloud:
nacos:
discovery:
# nacos服务器地址
server-addr: 127.0.0.1:8848
创建RestTemplate
的Bean:
package com.rtxtitanv.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.config.RestTemplateConfig
* @description RestTemplate配置类
* @date 2021/5/1 16:36
*/
@Configuration
public class RestTemplateConfig {
@Bean(name = "restTemplate")
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Controller层:
package com.rtxtitanv.controller;
import com.rtxtitanv.service.ConsumerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.ConsumerController
* @description ConsumerController
* @date 2021/4/30 18:02
*/
@RestController
public class ConsumerController {
@Resource
private ConsumerService consumerService;
@GetMapping("/test")
public String consumerTest() {
return consumerService.consumerTest();
}
}
Service层:
package com.rtxtitanv.service;
import reactor.core.publisher.Mono;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.service.ConsumerService
* @description ConsumerService
* @date 2021/5/1 16:34
*/
public interface ConsumerService {
/**
* 使用RestTemplate进行服务调用测试,使用LoadBalancerClient接口获取服务信息
*
* @return 调用nacos-discovery-provider返回的结果
*/
String consumerTest();
}
package com.rtxtitanv.service.impl;
import com.rtxtitanv.service.ConsumerService;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.service.impl.ConsumerServiceImpl
* @description ConsumerService实现类
* @date 2021/5/1 16:42
*/
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Resource
private RestTemplate restTemplate;
@Resource
private LoadBalancerClient loadBalancerClient;
@Override
public String consumerTest() {
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-discovery-provider");
String url = serviceInstance.getUri() + "/home";
return restTemplate.getForObject(url, String.class);
}
}
如下图所示方式启动三个服务提供者实例,端口分别为8091、8092、8093:
然后启动一个服务消费者实例,查看Nacos的管理页面中的服务列表,可见两个服务都已注册成功:
点击详情汉能查看每个服务具体的实例信息:
然后不断访问http://localhost:8080/test:
根据以上结果,可见每次请求访问的实例不同,可见实现了负载均衡。在通过LoadBalancerClient
接口在获取服务实例的时,已经实现了对服务提供者实例的负载均衡,默认使用轮询策略。由于SpringCloud 2020版本已经移除了Ribbon,所以在服务消费者中引入spring-cloud-starter-loadbalancer
依赖来代替Ribbon实现负载均衡。如果去掉spring-cloud-starter-loadbalancer
依赖,则服务消费者在启动时会报如下错误:
以上通过LoadBalancerClient
接口获取服务实例后拼接url的方式还可以进一步简化,通过@LoadBalanced
注解。在创建RestTemplate
类型的Bean的方法上需加上@LoadBalanced
注解:
@LoadBalanced
@Bean(name = "restTemplate")
public RestTemplate restTemplate() {
return new RestTemplate();
}
ConsumerController
中新增以下方法:
@GetMapping("/test1")
public String consumerTest1() {
return consumerService.consumerTest1();
}
ConsumerService
中新增以下方法:
String consumerTest1();
ConsumerServiceImpl
中实现该方法:
@Override
public String consumerTest1() {
return restTemplate.getForObject("http://nacos-discovery-provider/home", String.class);
}
重新启动服务消费者后不断访问http://localhost:8080/test1:
如果去掉服务消费者中的 spring-cloud-starter-loadbalancer
依赖,则在服务调用的时候会报如下错误(将之前LoadBalancerClient
相关代码注释掉再进行测试):
在进行服务调用时,Spring Cloud拦截请求,通过负载均衡器从服务列表中选出节点,并替换服务名部分为具体的ip和端口,实现基于服务名的负载均衡调用。
使用Spring WebFlux中的WebClient可以通过响应式编程的方式异步访问服务端接口。首先在服务消费者中引入依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
dependency>
创建WebClient.Bulider
的Bean:
package com.rtxtitanv.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.config.WebClientConfig
* @description WebClient配置类
* @date 2021/5/1 18:21
*/
@Configuration
public class WebClientConfig {
@LoadBalanced
@Bean(name = "webClientBuilder")
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
ConsumerController
中新增以下方法:
@GetMapping("/test2")
public Mono<String> consumerTest2() {
return consumerService.consumerTest2();
}
ConsumerService
中新增以下方法:
Mono<String> consumerTest2();
ConsumerServiceImpl
中实现该方法:
@Resource
private WebClient.Builder webClientBuilder;
@Override
public Mono<String> consumerTest2() {
return webClientBuilder.baseUrl("http://nacos-discovery-provider").build().get().uri("/home").retrieve()
.bodyToMono(String.class);
}
重新启动服务消费者后不断访问http://localhost:8080/test2:
如果去掉服务消费者中的 spring-cloud-starter-loadbalancer
依赖,则在服务调用的时候会报如下错误:
通过WebClient进行服务调用并实现负载均衡的实现原理在思想上与RestTemplate是相同的,都是通过添加相应的拦截器实现的。
使用Spring Cloud OpenFeign可以进行声明式的服务调用。首先引入依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
再在服务消费者主启动类上添加@EnableFeignClients
注解。然后编写声明式REST服务调用接口:
package com.rtxtitanv.feignclient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.feignclient.OpenFeignClient
* @description 声明式REST服务调用接口
* @date 2021/5/1 16:41
*/
@FeignClient(value = "nacos-discovery-provider")
public interface OpenFeignClient {
/**
* 声明式REST服务调用接口方法,调用服务nacos-discovery-provider的/home
*
* @return 调用nacos-discovery-provider返回的结果
*/
@GetMapping("/home")
String openFeignTest();
}
ConsumerController
中新增以下方法:
@GetMapping("/test3")
public String consumerTest3() {
return consumerService.consumerTest3();
}
ConsumerService
中新增以下方法:
String consumerTest3();
ConsumerServiceImpl
中实现该方法:
@Resource
private OpenFeignClient openFeignClient;
@Override
public String consumerTest3() {
return openFeignClient.openFeignTest();
}
重新启动服务消费者后不断访问http://localhost:8080/test3:
如果去掉服务消费者中的 spring-cloud-starter-loadbalancer
依赖,则服务消费者在启动时会报如下错误:
不同的服务可以归类到同一分组。通过spring.cloud.nacos.discovery.group
可以设置服务所处的分组,该配置项默认值为DEFAULT_GROUP,如果服务没设置分组,则默认处于DEFAULT_GROUP。
首先在服务提供者的application.yml
中新增以下配置:
spring:
cloud:
nacos:
discovery:
# 设置服务所处的分组,默认值为DEFAULT_GROUP
group: DEV-GROUP
然后启动3个服务提供者实例与1个服务消费者实例,查看Nacos的管理页面中的服务列表:
服务提供者与服务消费者处于两个不同的分组,进行服务调用时会出错,这里以访问http://localhost:8080/test1为例,服务消费者中会报以下错误:
通过分组可以将不同分组的服务隔离开来,下面在服务消费者的application.yml
中也新增以下配置:
spring:
cloud:
nacos:
discovery:
# 设置服务所处的分组,默认值为DEFAULT_GROUP
group: DEV-GROUP
重启服务消费者,刷新Nacos的管理页面中的服务列表:
可见服务提供者与服务消费者已经处于同一个分组DEV-GROUP,不断访问http://localhost:8080/test1:
Nacos数据模型Key由三元组唯一确定,Namespace(命名空间)默认是空串,公共命名空间(public),分组默认是DEFAULT_GROUP
:
命名空间(Namespace)用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
在Nacos的管理页面中的命名空间菜单下新建dev,test,prod三个命名空间:
建立好所有命名空间后,在配置管理与服务管理模块下所有页面,都会包含用于切换命名空间的按钮:
注意:
- 命名空间public是nacos的一个保留空间,如果需要创建自己的命名空间,不要和public重名,以一个实际业务场景有具体语义的名字来命名,以免带来字面上不容易区分自己是哪一个命名空间。
spring.cloud.nacos.discovery.namespace
配置项的值为命名空间ID,而不是名称。
通过spring.cloud.nacos.discovery.namespace
可以设置服务所处的命名空间,如果服务没设置命名空间,默认处于public命名空间。
首先在服务提供者的application.yml
中新增以下配置:
spring:
cloud:
nacos:
discovery:
# 设置服务所处的命名空间,通过命名空间的ID来指定命名空间,这里设置为命名空间dev
namespace: d8830907-76c9-4b18-a670-789f4290b8b5
在服务消费者的application.yml
中新增以下配置:
spring:
cloud:
nacos:
discovery:
# 设置服务所处的命名空间,通过命名空间的ID来指定命名空间,这里设置为命名空间test
namespace: 374a5221-33fb-47b7-8ca1-4b0955c81c4c
然后启动3个服务提供者实例与1个服务消费者实例,查看Nacos的管理页面中命名空间dev的服务列表:
查看Nacos的管理页面中命名空间test的服务列表:
服务提供者与服务消费者处于两个不同的命名空间,进行服务调用时会报与同一命名空间下不同分组之间的服务调用相同的错误,这里以访问http://localhost:8080/test1为例:
通过命名空间可以隔离不同环境下的资源(配置、服务),下面将服务消费者的命名空间设置改为命名空间dev的IDd8830907-76c9-4b18-a670-789f4290b8b5
,重启服务消费者,刷新Nacos的管理页面中命名空间dev的服务列表:
可见服务提供者与服务消费者已经处于同一个命名空间dev,不断访问http://localhost:8080/test1:
这里补充一下几个经常出现的概念的解释:
- 服务:通过预定义接口网络访问的提供给客户端的软件功能。
- 服务名:服务提供的标识,通过该标识可以唯一确定其指代的服务。
- 实例:提供一个或多个服务的具有可访问网络地址(IP:Port)的进程。
- 元信息:Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
- 权重:实例级别的配置。权重为浮点数。权重越大,分配给该实例的流量越大。
- 健康检查:以指定方式检查服务下挂载的实例(Instance)的健康度,从而确认该实例(Instance)是否能提供服务。根据检查结果,实例(Instance)会被判断为健康或不健康。对服务发起解析请求时,不健康的实例(Instance)不会返回给客户端。
- 健康保护阈值:为了防止因过多实例(Instance)不健康导致流量全部流向健康实例(Instance),继而造成流量压力把健康实例(Instance)压垮并形成雪崩效应,应将健康保护阈值定义为一个0到1之间的浮点数。当域名健康实例(Instance)占总服务实例(Instance)的比例小于该值时,无论实例(Instance)是否健康,都会将这个实例(Instance)返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例(Instance)能正常工作。
同一个服务下的所有服务实例组成一个默认集群,集群可以被进一步按需求划分,划分的单位可以是虚拟集群。通过spring.cloud.nacos.discovery.cluster-name
可以设置集群名称,相同集群下的实例才能互相感知。
在服务提供者的application.yml
中新增以下配置:
spring:
cloud:
nacos:
discovery:
# 设置集群名称,默认值为DEFAULT
cluster-name: ${CLUSTER_NAME:DEFAULT}
如下图所示方式启动集群名为PROVIDER1的三个服务提供者实例,端口分别为8091、8092、8093;启动集群名为PROVIDER2的三个服务提供者实例,端口分别为8094、8095、8096,然后再启动1个服务消费者实例:
启动后查看Nacos的管理页面中服务提供者所处的命名空间中的服务列表:
查看服务提供者详情信息:
不断访问http://localhost:8080/test1:
Nacos主页提供了一个服务管理菜单,能够查看、编辑当前注册的服务。服务管理菜单下的服务列表管理以统一的视图管理其所有的微服务以及服务健康状态。服务列表主要展示服务名、分组名称、集群数目、实例数、健康实例数等,点击详情可以看到服务的详情信息。重新启动3个服务提供者和1个服务消费者实例,均处于默认集群,两个服务都处于命名空间dev,服务列表信息如下:
在服务详情页面中可以修改实例的权重,权重为实例级别的配置,权重越大,分配给该实例的流量越大。如果不想实例接收流量,则可以将权重设为0:
不断访问http://localhost:8080/test1:
将端口为8093的实例的权重改回1后,不断访问http://localhost:8080/test1,端口为8093的实例将会重新接收流量,这里省略测试截图。
通过spring.cloud.nacos.discovery.metadata
可以自定义一些和服务相关的元数据信息,使用Map格式配置。
在服务提供者的application.yml
中新增以下配置:
spring:
cloud:
nacos:
discovery:
# 自定义服务的元数据信息,使用Map格式配置
metadata:
app.name: nacos-discovery-provider
app.version: 1.0.0
app.author: rtxtitanv
重启服务提供者的实例,在服务列表页面查看详情,可见设置的是实例的元数据:
在服务详情中的编辑服务中可以自定义服务的元数据,这些元数据以k-v格式存储。下面在元数据输入框输入service.description=Service Provider
:
点击确认之后服务的元数据就已经更新:
Nacos还提供服务实例的上下线操作,在服务详情页面中可以点击实例的“上线”或者“下线”按钮,被下线的实例将不会接收访问流量。正常启动3个服务提供者实例与1个服务消费者实例之后,根据之前的截图,可知对于服务提供者,健康的实例个数为3。不断访问http://localhost:8080/test1,3个实例都会接收访问流量,下面将端口为8092的实例下线:
不断访问http://localhost:8080/test1,发现端口为8092的实例已不再接收流量:
然后将端口为8092的实例恢复上线状态,再不断访问http://localhost:8080/test1,端口为8092的实例会重新接收访问流量。
Spring Cloud Alibaba官方文档中列出的常用的关于spring-cloud-starter-alibaba-nacos-discovery
的starter配置项如下所示:
配置项 | Key | 默认值 | 说明 |
---|---|---|---|
服务端地址 | spring.cloud.nacos.discovery.server-addr |
无 | Nacos Server启动监听的ip地址和端口 |
服务名 | spring.cloud.nacos.discovery.service |
${spring.application.name} |
给当前的服务命名 |
服务分组 | spring.cloud.nacos.discovery.group |
DEFAULT_GROUP |
设置服务所处的分组 |
权重 | spring.cloud.nacos.discovery.weight |
1 | 取值范围1到100,数值越大,权重越大 |
网卡名 | spring.cloud.nacos.discovery.network-interface |
无 | 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址 |
注册的IP地址 | spring.cloud.nacos.discovery.ip |
无 | 优先级最高 |
注册的端口 | spring.cloud.nacos.discovery.port |
-1 | 默认情况下不用配置,会自动探测 |
命名空间 | spring.cloud.nacos.discovery.namespace |
无 | 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等 |
AccessKey | spring.cloud.nacos.discovery.access-key |
无 | 当要上阿里云时,阿里云上面的一个云账号名 |
SecretKey | spring.cloud.nacos.discovery.secret-key |
无 | 当要上阿里云时,阿里云上面的一个云账号密码 |
Metadata | spring.cloud.nacos.discovery.metadata |
无 | 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息 |
日志文件名 | spring.cloud.nacos.discovery.log-name |
无 | |
集群 | spring.cloud.nacos.discovery.cluster-name |
DEFAULT |
配置成Nacos集群名称 |
接入点 | spring.cloud.nacos.discovery.enpoint |
UTF-8 |
地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 |
是否集成Ribbon | ribbon.nacos.enabled |
true |
一般都设置成true即可 |
是否开启Nacos Watch | spring.cloud.nacos.discovery.watch.enabled |
true |
可以设置成false来关闭 watch |
在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如WAR,JAR包等)更好地和实际的物理运行环境进行适配。
Nacos提供用于存储配置和其他元数据的key/value存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用Spring Cloud Alibaba Nacos Config,可以在Nacos Server集中管理Spring Cloud应用的外部属性配置。
Nacos官方文档对配置相关概念的解释:
- 配置项:一个具体的可配置的参数与其值域,通常以
param-key=param-value
的形式存在。- 配置集:一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。
- 配置集ID:Nacos中的某个配置集的ID。配置集ID是组织划分配置的维度之一。Data ID通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID通常采用类Java包的命名规则保证全局唯一性。此命名规则非强制。
- 配置分组:Nacos中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串对配置集进行分组,从而区分Data ID相同的配置集。当在Nacos上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认为
DEFAULT_GROUP
。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如database_url配置和MQ_topic配置。
首先在Nacos添加如下配置:
Data ID:nacos-config-client.properties
Group:DEFAULT_GROUP
配置格式:Properties
配置内容:user.name=Nero user.age=20
方式1:在命令行执行如下命令,向 Nacos Server 中添加一条配置:
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos-config-client.properties&group=DEFAULT_GROUP&content=user.name=Nero%0Auser.age=20"
执行命令之后查看配置列表,可见配置文件创建成功:
方式2:启动Nacos Server后,首先在Nacos的配置列表页面中点击右边的+号:
进入新建配置页面新建配置文件:
点击发布并确定之后查看配置列表,可见配置文件创建成功:
SpringBoot、SpringCloud和SpringCloudAlibaba依赖这里就不列出来了,还需引入以下依赖:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
主启动类这里就不贴出来了。编写配置文件,在bootstrap.yml
里进行如下配置:
server:
port: ${PORT:8000}
spring:
application:
name: nacos-config-client
cloud:
nacos:
config:
# nacos服务器地址
server-addr: 127.0.0.1:8848
必须使用
bootstrap
配置文件来配置Nacos Server地址。这里spring.application.name
值需与Nacos中创建的配置文件的Data Id匹配(除了.properties
或者.yaml
后缀)。因为dataId
的完整格式为${prefix}-${spring.profiles.active}.${file-extension}
,prefix
默认为spring.application.name
的值,spring.profiles.active
为当前环境对应的profile,这里该值为空,-
也将不存在,dataId的拼接格式变成${prefix}.${file-extension}
,file-exetension
为配置内容的数据格式,默认值为properties
。所以这里要加载的配置文件的dataId
为nacos-config-client.properties
,与Nacos中创建的配置文件一致。
创建测试用的Controller:
package com.rtxtitanv.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.ConfigClientController
* @description ConfigClientController
* @date 2021/5/5 18:15
*/
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${user.name:Unknown}")
private String userName;
@Value("${user.age:Unknown}")
private String userAge;
@GetMapping("/user")
public String getUser() {
return "user(userName=" + userName + ", userAge=" + userAge + ")";
}
}
在服务成功启动后会从Nacos Config Server中获取相应的配置,并添加在Spring Environment的PropertySources中。使用
@Value
注解可以将对应的配置项注入到ConfigClientController
的userName
和userAge
字段,@RefreshScope
实现配置动态刷新。
启动Config客户端服务,会发现并没有加载Bootstrap配置:
这是由于在SpringCloud 2020版,spring-cloud-commons提供的Bootstrap不再被默认启用。可以通过设置属性或引入一个新的启动器来启用Bootstrap上下文:
spring.cloud.bootstrap.enabled=true
或spring.config.use-legacy-processing=true
。这些属性需要作为环境变量、java系统属性或命令行参数来设置。spring-cloud-starter-bootstrap
依赖。在VM options中添加-Dspring.cloud.bootstrap.enabled=true
参数后可以启用Bootstrap上下文:
这里使用引入spring-cloud-starter-bootstrap
依赖的方式,依赖如下:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
dependency>
再次启动Config客户端服务会加载Bootstrap配置,部分启动日志截图如下:
访问http://localhost:8000/user,可见已经成功从Nacos Config Server获取到了配置文件中的数据:
spring-cloud-starter-alibaba-nacos-config
也支持配置的动态更新。Nacos Config Starter默认为所有获取数据成功的Nacos的配置项添加了监听功能,在监听到服务端配置发生变化时会实时触发org.springframework.cloud.context.refresh.ContextRefresher
的refresh方法。如果需要对Bean进行动态刷新,推荐给类添加@RefreshScope
或@ConfigurationProperties
注解。
修改配置文件nacos-config-client.properties
:
发布确认之后,该配置中的user.age
已被修改为21。再次访问http://localhost:8000/user,可见获取到了最新的数据:
可以通过配置
spring.cloud.nacos.config.refresh.enabled=false
来关闭动态刷新。
Nacos Config主要通过dataId和group来唯一确定一条配置。dataId的完整格式为${prefix}-${spring.profiles.active}.${file-extension}
:
prefix
默认为spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置。spring.profiles.active
即为当前环境对应的profile。当spring.profiles.active
为空时,对应的连接符-
也将不存在,dataId的拼接格式变成${prefix}.${file-extension}
。file-exetension
为配置内容的数据格式,默认值为properties
,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。group:
group
默认为 DEFAULT_GROUP
,可以通过spring.cloud.nacos.config.group
配置。前面的配置文件
nacos-config-client.properties
之所以能被加载,是因为使用默认值的服务加载配置的规则为dataId=${spring.application.name}.properties, group=DEFAULT_GROUP
,正好是该配置文件。
下面在Nacos新发布一个配置:
Data ID:user-config.properties
Group:DEFAULT_GROUP
配置格式:Properties
配置内容:user.name=Arthur user.age=18
查看配置列表以及配置详情:
配置文件user-config.properties
的dataId前缀与spring.application.name
的值不同,所以需要通过spring.cloud.nacos.config.prefix
可以指定dataId的prefix
为user-config
。在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
# 指定dataId的prefix,默认值为spring.application.name的值
# 这里确定要获取的配置文件的dataId的prefix为user-config
prefix: user-config
重启Config客户端服务后访问http://localhost:8000/user,可见获取到的是配置文件user-config.properties
中的数据:
spring-cloud-starter-alibaba-nacos-config
还支持yaml等多种配置格式。可以通过spring.cloud.nacos.config.file-extension
来指定dataId的后缀,也是配置的文件格式,获取指定格式的配置。
首先在Nacos发布几个不同格式的配置文件:
Data ID:user-config.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: Sora age: 22
Data ID:user-config.xml
Group:DEFAULT_GROUP
配置格式:XML
配置内容:<user> <name>Johnname> <age>25age> user>
Data ID:user-config.json
Group:DEFAULT_GROUP
配置格式:JSON
配置内容:{ "user": { "name": "William", "age": 23 } }
查看配置列表以及3个配置的详情:
在Config客户端服务的bootstrap.yml
配置文件中显示的声明dataId文件扩展名:
spring:
cloud:
nacos:
config:
# 指定dataId的后缀,同时也是配置的文件格式,默认值为properties
# 这里确定要获取的配置文件的格式为yaml
file-extension: yaml
重启Config客户端服务后访问http://localhost:8000/user,可见获取到的是配置文件user-config.yaml
中的数据:
将spring.cloud.nacos.config.file-extension
设置为xml
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是配置文件user-config.xml
中的数据:
将spring.cloud.nacos.config.file-extension
设置为json
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是配置文件user-config.json
中的数据:
最后将spring.cloud.nacos.config.file-extension
改回yaml
以便于之后的测试。
dataId的完整格式为${prefix}-${spring.profiles.active}.${file-extension}
,之前加载了dataId为${prefix}.${file-extension}
的基础配置,是因为没有通过spring.profiles.active
配置环境,spring.profiles.active
的值为空,连接符-
也就不存在,dataId的拼接格式就变成了${prefix}.${file-extension}
。如果需要在不同环境下使用不同配置,可以通过配置项spring.profiles.active
来配置。
首先在Nacos发布3个应用于不同环境下的配置:
Data ID:user-config-dev.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: dev-user age: 20
Data ID:user-config-test.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: test-user age: 21
Data ID:user-config-prod.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: prod-user age: 22
查看配置列表以及3个配置的详情:
在bootstrap.yml
中新增以下配置:
spring:
profiles:
# 配置当前环境对应的profile为dev
active: dev
这里是在配置文件中配置
spring.profiles.active=
,而在实际项目实施过程中该变量的值是需要不同环境下有不同的值。这时通常是通过-Dspring.profiles.active=
参数指定其配置来达到环境间灵活的切换。
重启Config客户端服务后访问http://localhost:8000/user,可见获取到的是配置文件user-config-dev.yaml
中的数据:
将spring.profiles.active
设置为test
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是配置文件user-config-test.yaml
中的数据:
将spring.profiles.active
设置为prod
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是配置文件user-config-prod.yaml
中的数据:
最后将spring.profiles.active
配置注释掉以便于之后的测试。
在没有明确指定${spring.cloud.nacos.config.group}
配置的情况下,默认使用的Group是DEFAULT_GROUP 。通过配置项spring.cloud.nacos.config.group
可以指定自定义的Group。
首先在Nacos发布3个处于不同Group的配置:
Data ID:user-config.yaml
Group:DEV_GROUP
配置格式:YAML
配置内容:user: name: dev-group-user age: 23
Data ID:user-config.yaml
Group:TEST_GROUP
配置格式:YAML
配置内容:user: name: test-group-user age: 24
Data ID:user-config.yaml
Group:PROD_GROUP
配置格式:YAML
配置内容:user: name: prod-group-user age: 25
查看配置列表以及3个配置的详情,可知这三个配置文件dataId相同,但Group不同:
要获取这三个配置文件中的任意一个,都需要指定它所属的Gruop,不然会获取属于DEFAULT_GROUP的user-config.yaml
。下面在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
# 指定Group,默认值为DEFAULT_GROUP
# 这里确定要获取的配置文件所属Group为DEV_GROUP
group: DEV_GROUP
该配置必须放在
bootstrap
配置文件中,并且在添加配置时Group的值一定要和spring.cloud.nacos.config.group
的配置值一致。
重启Config客户端服务后访问http://localhost:8000/user,可见获取到的是属于DEV_GROUP的配置文件user-config.yaml
中的数据:
将spring.cloud.nacos.config.group
设置为TEST-GROUP
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是属于TEST-GROUP的配置文件user-config.yaml
中的数据:
将spring.cloud.nacos.config.group
设置为PROD_GROUP
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是属于PROD_GROUP的配置文件user-config.yaml
中的数据:
最后将spring.cloud.nacos.config.group
注释掉以便于之后的测试。
在没有明确指定${spring.cloud.nacos.config.namespace}
配置的情况下, 默认使用的是Nacos上Public这个namespae(命名空间),通过配置项spring.cloud.nacos.config.namespace
可以指定要使用的自定义的命名空间。之前创建的3个命名空间如下:
在命名空间dev发布如下配置:
Data ID:user-config.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: dev-namespace-user age: 26
在命名空间test发布如下配置:
Data ID:user-config.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: test-namespace-user age: 27
在命名空间prod发布如下配置:
Data ID:user-config.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: prod-namespace-user age: 28
创建成功之后查看这3个命名空间的配置列表以及3个配置的详情,可见3个配置文件的dataId和group均相同,但分别处于3个不同的命名空间:
要获取这三个配置文件中的任意一个,都需要指定它所属的Namespace,不然会获取属于命名空间public的user-config.yaml
。下面在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
# 指定命名空间,必须通过命名空间的ID来指定,默认使用Nacos的public命名空间
# 这里确定要获取的配置文件所属的Namespace为dev
namespace: d8830907-76c9-4b18-a670-789f4290b8b5
该配置必须放在
bootstrap
配置文件中。spring.cloud.nacos.config.namespace
的值是namespace对应的id,id值可以在Nacos的控制台获取。并且在添加配置时注意不要选择其他的namespae,否则将会导致读取不到正确的配置。
重启Config客户端服务后访问http://localhost:8000/user,可见获取到的是命名空间dev中的配置文件user-config.yaml
中的数据:
将spring.cloud.nacos.config.namespace
设置为374a5221-33fb-47b7-8ca1-4b0955c81c4c
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是命名空间test中的配置文件user-config.yaml
中的数据:
将spring.cloud.nacos.config.namespace
设置为35be3a75-f528-4f10-b38f-acfaf1f1d4f5
后重启Config客户端服务,访问http://localhost:8000/user,可见获取到的是命名空间prod中的配置文件user-config.yaml
中的数据:
最后将spring.cloud.nacos.config.namespace
改回命名空间dev的id便于之后的测试。
Spring Cloud Alibaba Nacos Config支持自定义Data Id的配置。通过自定义扩展的Data Id配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件。
首先在命名空间dev发布3个配置:
Data ID:ext-config-common-test1.properties
Group:DEFAULT_GROUP
配置格式:Properties
配置内容:common.host=127.0.0.1 common.username=root common.password=root
Data ID:ext-config-common-test2.yaml
Group:GLOBALE_GROUP
配置格式:YAML
配置内容:common: host: 192.168.221.16 port: 6379 password: 123456
Data ID:ext-config-common-test3.json
Group:REFRESH_GROUP
配置格式:JSON
配置内容:{ "common": { "port": "3306", "password": "abcdef" } }
在ConfigClientController
中新增如下代码:
@Value("${common.host:Unknown}")
private String commonHost;
@Value("${common.port:Unknown}")
private String commonPort;
@Value("${common.username:Unknown}")
private String commonUsername;
@Value("${common.password:Unknown}")
private String commonPassword;
@GetMapping("/ext-config")
public String getExtConfig() {
return "common.host: " + commonHost + ", common.port: " + commonPort + ", common.username: " + commonUsername
+ ", common.password: " + commonPassword;
}
在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
# 自定义扩展的dataId配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件
extension-configs:
# dataId在默认的组DEFAULT_GROUP,不支持配置动态刷新
- data-id: ext-config-common-test1.properties
# dataId在GLOBALE_GROUP分组,不支持配置动态刷新
- data-id: ext-config-common-test2.yaml
# 配置dataId所在分组,缺省默认DEFAULT_GROUP
group: GLOBALE_GROUP
# dataId在REFRESH_GROUP分组,支持配置动态刷新
- data-id: ext-config-common-test3.json
group: REFRESH_GROUP
# 配置dataId在配置变更时,是否支持动态刷新,缺省默认false
refresh: true
多个Data Id同时配置时,优先级关系是
spring.cloud.nacos.config.extension-configs
数组下标值越大,优先级越高。spring.cloud.nacos.config.extension-configs[n].data-id
的值必须带文件扩展名,spring.cloud.nacos.config.file-extension
的配置对自定义扩展配置的Data Id文件扩展名没有影响。
重启Config客户端服务,除了加载了通过内部规则${prefix}-${spring.profiles.active}.${file-extension}
自动生成的dataId为user-config.yaml
的配置外,通过spring.cloud.nacos.config.extension-configs
配置的3个配置文件也被加载:
访问http://localhost:8000/ext-config:
根据返回的结果可以验证,spring.cloud.nacos.config.extension-configs
配置的多个Data Id有相同的配置项时,优先级关系是spring.cloud.nacos.config.extension-configs
数组下标值越大,优先级越高。修改配置文件ext-config-common-test3.json
下的common.password
:
访问http://localhost:8000/ext-config,由于配置了ext-config-common-test3.json
在变更时支持动态刷新,所以获取到了最新的值:
修改ext-config-common-test2.yaml
的common.host
:
访问http://localhost:8000/ext-config,由于未配置dataId为ext-config-common-test2.yaml
的refresh
,默认不支持动态刷新,获取不到变更后的值:
可以通过spring.cloud.nacos.config.shared-configs
更加清晰的在多个应用间配置共享Data Id。下面在命名空间dev发布3个配置:
Data ID:share-config-test1.properties
Group:DEFAULT_GROUP
配置格式:Properties
配置内容:share.username=root share.hostname=share-server log.level=warning
Data ID:share-config-test2.yaml
Group:GLOBALE_GROUP
配置格式:YAML
配置内容:share: username: admin password: 123456 log: level: info
Data ID:share-config-test3.json
Group:REFRESH_GROUP
配置格式:JSON
配置内容:{ "share": { "password": "admin" } "log": { "level": "debug" } }
在ConfigClientController
中新增如下代码:
@Value("${share.username:Unknown}")
private String shareUsername;
@Value("${share.password:Unknown}")
private String sharePassword;
@Value("${share.hostname:Unknown}")
private String shareHostname;
@Value("${log.level:Unknown}")
private String logLevel;
@GetMapping("/share-config")
public String getShareConfig() {
return "share.username: " + shareUsername + ", share.password: " + sharePassword + ", share.hostname: "
+ shareHostname + ", log.info: " + logLevel;
}
在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
# 配置共享的dataId
shared-configs:
# dataId在默认的组DEFAULT_GROUP,不支持配置动态刷新
- data-id: share-config-test1.properties
# dataId在GLOBALE_GROUP分组,不支持配置动态刷新
- data-id: share-config-test2.yaml
# 配置dataId所在分组,缺省默认DEFAULT_GROUP
group: GLOBALE_GROUP
# dataId在REFRESH_GROUP分组,支持配置动态刷新
- data-id: share-config-test3.json
group: REFRESH_GROUP
# 配置dataId在配置变更时,是否支持动态刷新,缺省默认false
refresh: true
重启Config客户端服务,发现通过spring.cloud.nacos.config.shared-configs
配置的共享配置文件会被加载:
访问http://localhost:8000/share-config:
根据返回的结果可以验证,spring.cloud.nacos.config.shared-configs
配置的多个Data Id有相同的配置项时,优先级关系是spring.cloud.nacos.config.shared-configs
数组下标值越大,优先级越高。spring.cloud.nacos.config.shared-configs[n].refresh
和spring.cloud.nacos.config.extension-configs[n].refresh
都是来控制该Data Id在配置变更时,是否支持应用中动态刷新,默认false,关于共享dataId的配置的动态刷新的测试结果和自定义扩展dataId的配置类似,这里就省略了。
Spring Cloud Alibaba Nacos Config目前提供了三种配置能力从Nacos拉取相关的配置。
spring.cloud.nacos.config.shared-configs[n].data-id
支持多个共享 Data Id 的配置。spring.cloud.nacos.config.extension-configs[n].data-id
的方式支持多个扩展 Data Id 的配置。${prefix}-${spring.profiles.active}.${file-extension}
,spring.cloud.nacos.config.group
)自动生成相关的Data Id配置。当三种方式共同使用时,他们的一个优先级关系是:A < B < C。
下面来验证一下,先在命名空间dev发布2个配置:
Data ID:priority-extension-configs.yaml
Group:REFRESH_GROUP
配置格式:YAML
配置内容:user: name: admin age: 20 log: level: debug
Data ID:priority-shared-configs.yaml
Group:REFRESH_GROUP
配置格式:YAML
配置内容:user: name: root pwd: 123456 log: level: info
通过内部相关规则自动生成的Data Id的配置,位于命名空间dev(该配置是之前创建的):
Data ID:user-config.yaml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:user: name: dev-namespace-user age: 26
在ConfigClientController
中新增如下代码:
@Value("${user.pwd:Unknown}")
private String userPwd;
@GetMapping("/priority")
public String configPriority() {
return "user.name: " + userName + ", user.age: " + userAge + ", user.pwd: " + userPwd + ", log.info: "
+ logLevel;
}
在bootstrap.yml
中新增以下配置:
spring:
cloud:
nacos:
config:
extension-configs:
# 该dataId配置用于测试配置优先级
- data-id: priority-extension-configs.yaml
group: REFRESH_GROUP
refresh: true
shared-configs:
# 该dataId配置用于测试配置优先级
- data-id: priority-shared-configs.yaml
group: REFRESH_GROUP
refresh: true
重启Config客户端服务,访问http://localhost:8000/priority:
根据以上结果可知,3种类型的配置均有user.name
,而最终获取到的user.name
的结果为user-config.yaml
中user.name
的值,说明C的优先级最高,而A和B均有log.level
,而最终获取到的log.level
的结果为priority-extension-configs.yaml
中log.level
的值,说明B的优先级高于A,所以综上可知优先级顺序为A < B < C。
通过设置
spring.cloud.nacos.config.enabled = false
来完全关闭 Spring Cloud Nacos Config。
代码示例