Nacos配置管理应用于分布式系统
从单体架构到微服务
单体架构
Web应用程序早期,大部分的web工程师将所有的功能模块打包到一一起并放在一个web容器中运行,所有功能模块使用同一个数据库,同时,它还提供API和UI访问的web模块等。
尽管也是模块化逻辑,但是最总它还是会打包成一个单体应用,这种将所有功能部署在一个web容器中运行的系统就叫做单体架构。
优点:
开发效率高:模块之间交互采用本地调用,并节省微服务之间的交互讨论时间和开发成本
容易测试:IDE都是为开发单个应用而设计,容易测试,直接在本地就可以启动完整的系统
容易部署:运维成本小,直接打包为一个完整的包,复制到web容器之下即可运行。
缺点:
复杂性逐渐变高,可维护性差:所有业务部署在一起,复杂度越来越高,牵一发而动全身。
版本迭代速度逐渐变慢:修改一个地方就要将整个应用全部编译部署,启动时间长,回归测试时间过长。
微服务
许多大型公司,通过采用微服务架构解决上面的问题。其思路不是开发一个大的单体应用,而是将其应用分解为小的,互相连接的微服务。
一个微服务一般完成某个特定的功能,比如订单服务,用户服务等。每一个微服务都是完整应用,都有自有的业务逻辑和数据库。一些微服务还会发布API给其它微服务和应用客户端使用。
比如,根据前面描述的系统可分解如下:
每一个业务模块都使用独立的服务完成,这种微服务架构模式也影响了应用和数据库之间的关系,不像传统多个业务模块共享一个数据库,微服务架构每个服务都有自己的数据库。
微服务好处:
分而治之,职责单一: 易于开发,理解和维护,方便团队的拆分和管理
可伸缩: 能够单独的对指定的服务进行伸缩
局部容易修改,容易替换,容易部署,有利于持续集成和快速迭代
不会受制于任何技术栈
分布式应用配置管理
发布配置
在nacos发布配置,我们规划了两个服务service01,service02,并且想对这两个服务的配置进行集中维护。
在nacos中添加配置
对应的内容
#service01.yaml
Namespace: 命名空间Id #开发环境
Data ID:service1.yml
Group:TEST——Group
配置格式:YAML
配置内容: person:
name: xiaowang from service01
#service02.yaml
Namespace: 命名空间Id #开发环境
Data ID:service1.yml
Group:TEST——Group
配置格式:YAML
配置内容:person:
name: xiaoming from service02
创建父工程
(1) 新建一个maven工程
(2)引入依赖pom.xml,配置依赖管理和插件
<!--配置依赖管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</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>
微服务service01配置
本小节,我们将演示如何使用Spring Cloud Alibaba Nacos Config 在Spring Cloud应用集中Nacos,通过Spring Cloud原生方式快捷的获取配置内容
SpringCloud是什么?
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
Spring Cloud Alibaba Nacos Config是什么?
Spring Cloud Alibaba Nacos Discovery 是 Spring Cloud Alibaba的子项目,而Spring Cloud Alibaba是阿里巴巴公司提供的开源的基于Spring Cloud微服务套件集合,它致力于提供微服务开发的一站式的解决方案,可以理解为SPring cloud 是一套微服务的开发标准,SPring cloud alibaba和SPring cloud Netifix是实现。使用Spring Cloud Alibaba方案,开发者只需要添加一些注解和少量配置就可以将Spring Cloud应用接入阿里分布式解决方案,通过阿里中间件来迅速搭建分布式应用系统。
由于Nacos是阿里的中间件。因此,若开发SPring Cloud微服务应用,使用 Spring Cloud Alibaba Nacos Config集成Nacos的配置管理是明智的选择。
新建子工程service01
(2) 引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在resources文件夹下配置bootstrap.yml文件
一般来说,Spring boot的配置将在application.yml(也可以是application.properties)文件编写,由于使用了外部配置中心,必须将原先的application.yml重命名为bootstrap.yml,bootstrap.yml如下示例:
server:
port: 10001 #启动端口
spring:
application:
name: service01 #项目名
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #文件扩展名,dataid的名称就是application.name+file-extension,即为service01.yaml
namespace: 869a0c6d-267e-4aa1-96cb-552cb1632c72 #开发环境dev的id(nacos命名空间下找dev对应的id)
group: TEST_GROUP #测试组
以上配置文件说明应用将从地址为127.0.0.1:8848配置中心获取配置,通过以下信息定位配置集。
启动配置客户端
新增Spring Boot启动类,并增加了获取配置的web访问端口/config,通过标准的Spring @Value的方式
@RestController
public class HelloController {
@Value("${person.name}")
private String name;
@GetMapping("/hello")
public String hello(){
//读取配置信息
return name;
}
}
编写启动类
package com.it2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Service01Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service01Bootstrap.class,args);
}
}
运行启动类,并访问controller,可以看到能获取到nacos的配置
微服务service02
service02和service01流程一致
需要注意的是Spring Boot启动端口避免重复,Spring.application.name为Service02.
server:
port: 10002 #启动端口
spring:
application:
name: service02 #项目名
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #文件扩展名,dataid的名称就是application.name+file-extension,即为service01.yaml
namespace: 869a0c6d-267e-4aa1-96cb-552cb1632c72 #开发环境dev的id(nacos命名空间下找dev对应的id)
group: TEST_GROUP #测试组
分别启动Service01和Service02项目,并且访问/config进行测试,不同项目可以获取各自的配置内容。
支持配置的动态更新
基于上面快速上手的例子,若要实现配置的动态更新,只需要进行如下改造:
@RestController
public class HelloController {
@Value("${person.name}")
private String name;
@Autowired
ConfigurableApplicationContext applicationContext;
@GetMapping("/hello")
public String hello(){
//读取配置信息
return name+"--------"+applicationContext.getEnvironment().getProperty("person.name");
}
}
我们通过Nacos控制台更新common.name的配置值,再次访问web端口/configs,发现应用程序能够获取到更多的配置,说明Spring-cloud-start-alibaba-nacos-config支持配置的动态更新。
Note可以通过配置Spring.cloud.nacos.config.refresh.enable=false来关闭动态刷新。
自定义namespace和group配置
支持自定义namespace的配置
在没有明确指定${spring.cloud.nacos.config.namespace}配置的情况下,默认使用nacos上的Public这个namespace。如果需要使用自定义的命名空间,可以通过如下配置实现:
spring:
cloud:
nacos:
config:
namespace: 869a0c6d-267e-4aa1-96cb-552cb1632c72 #namespace的id
注意:该配置必须放在bootstrap.ym或者bootstrap.propertiesl文件中。此外spring.cloud.nacos.config.namespace的值是namespace对应的id,id值可以在nacos的控制台获取。并且在添加配置时注意不要选择其它的namespace,否则将会导致读取不到正确的配置。
支持自定义Group的配置
在没有明确指定${spring.cloud.nacos.config.group}配置的情况下,默认使用是DEFAULT_GROUP。如果需要自定义自己的group,可以通过一下配置来实现:
spring:
cloud:
nacos:
config:
group: TEST_GROUP #测试组
注意:该配置必须放在bootstrap.yml或者bootstrap.properties文件中。并且在添加配置时group的值一定要和spring.cloud.nacos.config.group的配置一致。
自定义扩展的Data Id配置
Spring Cloud Alibaba Nacos Config可支持自定义Data Id的配置。一个完整的的配置案例如下:
下边我们在Service2微服务下配置扩展。
server:
port: 10002 #启动端口
spring:
application:
name: service02
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #文件扩展名,dataid的名称就是application.name+file-extension,即为service01.yaml
namespace: 869a0c6d-267e-4aa1-96cb-552cb1632c72 #开发环境dev的id(nacos命名空间下找dev对应的id)
group: TEST_GROUP #测试组
# 扩展文件
# 1. Data Id在默认的组DEFAULT_GROUP,不支持配置的动态刷新
ext-config[0]:
data-id: ext-config01.properties
ext-config[1]:
# 2. Data Id 不在默认的组,不支持动态刷新
data-id: ext-config02.properties
group: TEST2_GROUP
# 3. Data Id不在默认的组,支持动态刷新
ext-config[2]:
data-id: ext-config03.properties
group: TEST3_GROUP
refresh: true
可以看到:
通过Spring.cloud.nacos.config.ext-config[n].data-id的配置方式来支持多个Data Id的配置。
通过Spring.cloud.nacos.config.ext-config[n].group的配置方式来自定义Data Id所在的组,不明确配置的话,默认是DEFAULT_GROUP
通过Spring.cloud.nacos.config.ext-config[n].refresh的配置方式来控制该Data Id在配置变更时,是否支持应用中可以动态刷新,感知到最新的配置值。默认是不支持的。
Nacos.Spring.cloud.nacos.config.ext-config[n].data-id的值必须带文件扩展名,文件扩展名既可以支持properties。又可以支持yaml/yml。此时Spring.cloud.nacos.config.file-extension的配置对自定义扩展配置的Data Id文件扩展名没有影响。
通过自定义扩展的Data Id配置,既可以解决多个应用配置共享的问题,又可以支持一个应用有多个配置文件。
测试:
在nacos后台配置了三个配置
三个扩展文件的内容分别如下
配置ext-config.common01.properties:
config01.name=1
配置ext-config.common02.properties:
config02.name=2
配置ext-config.common03.properties:
config03.name=3
编写测试代码:
@RestController
public class HelloController {
@Value("${person.name}")
private String name;
@Autowired
ConfigurableApplicationContext applicationContext;
@GetMapping("/hello")
public String hello(){
System.out.println("=====================");
System.out.println(applicationContext.getEnvironment().getProperty("config01.name"));
System.out.println(applicationContext.getEnvironment().getProperty("config02.name"));
System.out.println(applicationContext.getEnvironment().getProperty("config03.name"));
return name;
}
}
在项目启动后,此时分别将值改成11,22,33,打印输出结果,只有第三个显示33,表明了 refresh: true可以热刷新。
总结
通过spring.cloud.nacos.config.ext-config[n].data-id的配置方式来支持多个Data Id的配置,同时文件必须指定扩展名,支持properties和yaml,此扩展名与spring.cloiud.nacos.config.file-extension的配置对自定义扩展配置的Data Id文件扩展名没有关系。
通过spring.cloud.nacos.config.ext-config[n],group的配置方式自定义Data Id所在的分组,未指定的情况下默认是DEFAULT_GROUP
通过spring.cloud.nacos.ext-config[n].refresh的配置方式来控制该Data Id在配置变更时,是否支持应用中可动态刷新,感知到最新的配置值。默认为false,不支持热刷新。
通过自定义扩展的Data Id配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置。
自定义共享的Data Id配置(不推荐)
为了更加清晰的在多个应用间配置共享的Data Id,你可以通过一下的方式来配置:
server:
port: 10001 #启动端口
spring:
application:
name: service01
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心
file-extension: yaml #文件扩展名,dataid的名称就是application.name+file-extension,即为service01.yaml
namespace: 869a0c6d-267e-4aa1-96cb-552cb1632c72 #开发环境dev的id(nacos命名空间下找dev对应的id)
group: TEST_GROUP #测试组
#共享Data Id只支持DEFAULT_GROUP
shared-dataids: ext-config01.properties,ext-config02.properties #共享的Data Id
refreshable-dataids: ext-config01.properties #热刷新的Data Id
总结:
通过spring.cloud.nacos.config.shared-dataids来支持多个共享Data Id的配置,多个之间以逗号隔开。
通过spring.cloud.nacos.config.refreshable-dataids来支持哪些共享配置的Data Id在配置变化时,应用是否动态刷新,获取最新的值,多个Data Id之间以逗号隔开。如果没有生命,默认情况下所有共享配置的Data Id都不支持动态刷新。
通过spring.cloud.nacos.config.shared-dataids来支持多个共享配置的Data Id时,多个共享配置间的一个优先级的关系约定:按照配置出现的先后顺序,即后面的优先级高于前面。
配置优先级
Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从nacos拉取配置
A 通过spring.cloud.nacos.config.shared-dataids支持多个共享Data Id的配置
B 通过spring.cloud.nacos.ext-config[n].data-id的方式支持多个扩展Data Id的配置,多个Data Id同时配置时,优先级顺序:后面的配置覆盖前面,即后面优先级更高。
C 通过内部相关规则(应用,扩展名)自动生成相关的Data Id配置
当三种方式共同存在时,优先级C > B >A
测试,屏蔽共享dataId,放开ext-config如下:
验证B:
分别在ext-config01.properties和ext-config02.properties配置内容name=01和name=02
然后输出name,可以看到ext-config02.properties的优先级高于ext-config01.properties
验证C> B
此时修改service02.yaml,增加name=service.yaml
同时运行输出name,输出的name为service02.yaml的配置内容,说明C>B
完全关闭配置
通过设置Spring.cloud.nacos.config.enabled=false来完全关闭Spring Cloud Nacos Config