分布式应用配置管理
用户通过Nacos Server的控制台集中对多个服务的配置进行管理。
各服务统一从Nacos Server中获取各自的配置,并监听配置的变化。
我们在命名空间为dev的环境下测试
发布配置
首先在nacos发布配置,我们规划了两个服务service1、service2 ,并且想对这两个服务的配置进行集中维护。
在Nacos添加如下的配置:
创建父工程
规范依赖
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependenices</artifactId>
<version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
微服务service1/2配置
Spring Cloud是什么:
Spring Cloud是一系列框架的有序集合。 它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发, 如服务发现注册、配置中心I消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,集成最多的组件要属Netflix公司,通过Spring Boot风格进行
再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、 易部署和易维护的分布式系统开发工具包。
Spring Cloud Alibaba 是什么
Spring Cloud Alibaba Nacos Discovery是Spring Cloud Alibaba的子项目,而Spring Cloud Alibaba是阿里巴巴公司提供的开源的基于Spring cloud的微服务套件合集,它致力于提供微服务开发的一站式解决方案,可以理解为spring cloud是一套微服务开发的 标准, spring cloud alibaba 与spring cloud Netflix是实现。使用Spring Cloud Alibaba方案,开发者只需要添加一些注解和少量配置,就可以将Spring Cloud应用
接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。
由于Nacos是阿里的中间件,因此,若开发Spring cloud微服务应用,使用Spring Cloud Alibaba NacosConfig来集成Nacos的配置管理功能是比较明智的选择。
新建项目service1
首先新增一个名为service1工程 ,并添加group ID为com. alibaba.cloud和artifact ID为spring-cloud-starter-alibaba-nacos-config的starter.
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
配置文件编写
一般来说 ,spring boot的配置将在application.yml(也可以是application.properties)文件中编写,由于使用外部配置中心,必须将原先的application.yml重命名为bootstrap.yml , bootstrap.ym如下所示:
为什么不写进我们的application.yml中呢?
因为我们的bootstarp的加载顺序优先于我们的application
server:
port: 56010 #启动端口号 命令行注入
spring:
application:
name: service1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #配置文件后缀名 dataId = application.name + file-extension
namespace: ea8fdc12-3509-472b-b8a9-5145f7e5ce85 #开发环境
group: TEST_GROUP #测试组
编写启动客户端
@SpringBootApplication
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
}
service2的方式都一样,不过就是名称改一改,2的server.prot端口号换一个就行了
测试
@SpringBootApplication
@RestController
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
@Value("${common.name}")
private String config1;
@GetMapping("/configs")
public String getConfig(){
//读取配置信息
return config1;
}
}
启动访问我们的localhost:56010/configs,得到我们想要的配置
注意nacos更改配置后,我们刷新是获取不到最新的配置值的,是没通知到么?
不是,实际上这个通知已经产达到了,但是我们的value注解并没有把最新的配置进行赋值的,怎么做到动态更新呢?
支持配置的动态更新
利用Spring的上下文机制来动态更新
@SpringBootApplication
@RestController
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
@Autowired
ConfigurableApplicationContext applicationContext;
@GetMapping("/configs")
public String getConfig(){
//读取配置信息
return applicationContext.getEnvironment().getProperty("common.name");
}
}
使用这种方式,nacos配置中心更改配置之后,我们直接刷新请求就可以动态更新了
自定义namespace与group
在没有明确指定${spring.cloud.nacos.config.namespace}配置的情况下,默认使用的是Nacos上Public这个namespace.如果需要使用自定义的命名空间,可以通过以下配置来实现:
自定义扩展DataId配置
假如我们一个service要使用一些公共的配置,不止一个的时候怎么解决
Spring Cloud Alibaba Nacos Config可支持自定义Data ld的配置。一个完整的配置案例如下所示:
server:
port: 56010 #启动端口号 命令行注入
spring:
application:
name: service1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #配置文件后缀名 dataId = application.name + file-extension
namespace: ea8fdc12-3509-472b-b8a9-5145f7e5ce85 #开发环境
group: TEST_GROUP #测试组
#扩展dataId
#1.DataId 在默认的组DEFAULT_GROUP下,不支持配置的动态刷新
ext-config[0]:
data-id: ext-config-common01.properties
#dataId 不在默认的组,不支持动态刷新
ext-config[1]:
data-id: ext-config-common02.properties
group: GLOBALE_GROUP
#dataId 既不在默认的组,也支持动态刷新
ext-config[2]:
data-id: ext-config-common03.properties
group: REFREH_GROUP
refresh: true
配置1
配置2
配置3
测试
@SpringBootApplication
@RestController
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
@Autowired
ConfigurableApplicationContext applicationContext;
@GetMapping("/configs")
public String getConfig(){
//读取配置信息
return applicationContext.getEnvironment().getProperty("common.name");
}
@GetMapping("/configs2")
public String getConfig2(){
String name = applicationContext.getEnvironment().getProperty("common.name");
String age = applicationContext.getEnvironment().getProperty("common.age");
String address = applicationContext.getEnvironment().getProperty("common.address");
String birthday = applicationContext.getEnvironment().getProperty("common.birthday");
String fullname = applicationContext.getEnvironment().getProperty("common.fullname");
return name + "+" + age + "+" + address + "+" + birthday + "+" + fullname;
}
}
能读取到么?不在一个组
是可以读取到的,然后我们再去分别修改修改这三个配置,然后刷新我们的请求看看能不能动态刷新
我们可以看到,只有我们的第三个配置文件可以动态刷新
自定义共享DataId配置
为了更加清晰的在多个应用间配置共享的Data Id ,你可以通过以下的方式来配置:
spring:
cloud:
nacos:
config:
shared-dataids: ext-config-common01. properties,ext-config-common02.properties
refreshable-dataids: ext-config-common01.properties
#刷新某个配置文件
可以看到:
●通过(spring.cloud. nacos . config. shared-dataids 来支持多个共享Data ld的配置,多个之间用逗号隔开。
●通过spring.cloud.nacos . config. refreshable-dataids来支持哪些共享配置的Data ld在配置变化时,应用中是否可动态刷新,感知到最新的配置值,多个Data Id之间用逗号隔开。如果没有明确配置,默认情况下所有共享配置的Data ld都不支持动态刷新。
server:
port: 56010 #启动端口号 命令行注入
spring:
application:
name: service1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #配置文件后缀名 dataId = application.name + file-extension
namespace: ea8fdc12-3509-472b-b8a9-5145f7e5ce85 #开发环境
group: TEST_GROUP #测试组
shared-dataids: ext-config-common01.properties,ext-config-common02.properties,ext-config-common03.properties
refreshable-dataids: ext-config-common01.properties
为啥我第二个配置文件和第三个配置文件不生效了呢?
因为这种共享的id方式只认我们的DEFAULT_GROUP的东西其他的不认
配置优先级
享配置的Data ld在配置变化时,应用中是否可动态刷新,感知到最新的配置值,多个Data Id之间用逗号隔开。如果没有明确配置,默认情况下所有共享配置的Data ld都不支持动态刷新。
server:
port: 56010 #启动端口号 命令行注入
spring:
application:
name: service1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #配置文件后缀名 dataId = application.name + file-extension
namespace: ea8fdc12-3509-472b-b8a9-5145f7e5ce85 #开发环境
group: TEST_GROUP #测试组
shared-dataids: ext-config-common01.properties,ext-config-common02.properties,ext-config-common03.properties
refreshable-dataids: ext-config-common01.properties
为啥我第二个配置文件和第三个配置文件不生效了呢?
因为这种共享的id方式只认我们的DEFAULT_GROUP的东西其他的不认
配置优先级
Spring Cloud Alibaba Nacos Config目前提供了三种配置能力从Nacos拉取相关的配置。
A:通过spring. cloud.nacos . config. shared-dataids支持多个共享Data Id的配置
B:通过spring. cloud. nacos . config . ext-config[n].data-id的方式支持多个扩展Data ld的配置,多个Data Id同时配置时,他的优先级关系是‘spring. cloud. nacos . config. ext -config[n].data-id其中 n的值越大,优先级越高.
C:通过内部相关规则(应用名、扩展名)自动生成相关的Data ld配置
当三种方式共同使用时,他们的一个优先级关系是:C>B>A
完全关闭配置
通过设置spring.cloud.nacos.config.enabled = false来完全关闭Spring Cloud Nacos Config