我们首先来看下在微服务架构下为什么需要使用注册中心?
从下图我们可以看出,在微服务架构下会有多个模块,每个模块在application文件下都维护了很多配置信息,比如数据库,注册中心等。
这个时候如果有某个统一配置需要修改,比如我们四个模块的注册地址都是相同的,这个时候注册地址需要修改,那我们岂不是需要去修改四个文件,可能现在文件少大家觉得很简单,但是如果需要修改四十个文件呢?所以我们需要配置中心来帮助我们统一管理相关的配置信息。
加入配置中心统一管理后,这个架构就变成下图所示:
我们将相关配置信息交给配置中心进行管理,服务启动的时候我们直接从配置中心同步相关数据;然后我们的统一配置中心还需要提供一个控制台交由我们进行相关数据的修改,比如熔断是否开启的配置,超时时间等等啊;最后我们修改完数据后,还能支持我们进行配置项的同步。
这便是引入配置中心后的大致流程,但一个好的配置中心并不是只有这些功能,它应该具备如下几个功能:
- 可视化的配置维护
- 高可用集群
- 数据的存储(持久化)
- 配置中心本身的安全性
- 配置变更的动态同步
目前市面比较常用的配置中心有很多:
- Zookeeper
- Etcd
- Disconf
- Nacos
- Apollo
- Consul
- Spring cloud config
本文主要介绍Nacos这款中间件,它的前身为Diamond,是阿里巴巴开源中间件,由于是国产的,所以它的文档很详细,方便我们进行学习。
它为我们提供了两种功能:
- 服务注册与发现
- 配置管理
1. Nacos 搭建
- 官网下载
- 执行
startup.cmd -m standalone(Linux 执行 sh文件即可) - 访问
http://localhost:8848/nacos - 账号密码 nacos/nacos
2. 配置管理使用
我们可以在配置列表中添加相关配置信息,提供多种类型的数据格式供我们选择。
Data Id是每个配置项的唯一标识,用来对配置进行对应的区分。Group相关会在后面讲解命名空间的时候了解。
那我们如何获取相关数据呢?我们搭建一个spring boot项目来测试下。(版本之间会有以下对应关系,大家可自行在官网查看,我这里使用spring boot : 2.3.12.release,nacos:1.4.2)
2.1 Api使用
- 引入依赖,这里先不引用集成依赖。
<!-- nacos 配置-->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.2</version>
</dependency>
- 测试类
这里我们可以使用Nacos提供的API实现获取配置中心的数据,通过监听可以实时获取变更的数据。
public class NacosMain {
public static void main(String[] args) throws NacosException, IOException {
ConfigService configService = NacosFactory.createConfigService("localhost:8848");
String context = configService.getConfig("nacos-demo", "DEFAULT_GROUP", 3000);
System.out.println(context);
// 监听数据变更
configService.addListener("nacos-demo", "DEFAULT_GROUP", new Listener() {
@Override
public Executor getExecutor() {
return null;
}
@Override
public void receiveConfigInfo(String s) {
System.out.println("收到配置变更的通知:" + s);
}
});
System.in.read();
}
}
2.2 集成Spring Boot
Spring boot 集成 nacos 整体来说还是很简单的,我们只需要几步即可完成:
- 引入依赖
<!-- springboot nacos 依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.8</version>
</dependency>
- 配置nacos 地址
nacos.config.server-addr=127.0.0.1:8848
-
启动类添加注解
dataId对应唯一值,autoRefreshed开启自动刷新。
@NacosPropertySource(dataId = "nacos-demo",autoRefreshed = true)
@SpringBootApplication
public class SpringBootNacosApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootNacosApplication.class, args);
}
}
-
获取配置信息
直接通过
NacosValue注解获取对应key的值即可。
@RestController
public class NacosConfigController {
@NacosValue(value = "${txt}", autoRefreshed = true)
private String txt;
@GetMapping("/txt")
public String get(){
return txt;
}
}
2.3 集成 Spring cloud
- 添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${latest.version}</version>
</dependency>
注意:版本 2.1.x.RELEASE 对应的是 Spring Boot 2.1.x 版本。版本 2.0.x.RELEASE 对应的是 Spring Boot 2.0.x 版本,版本 1.5.x.RELEASE 对应的是 Spring Boot 1.5.x 版本。
更多版本对应关系参考:版本说明 Wiki
- 在
bootstrap.properties中配置 Nacos server 的地址和应用名
为什么放在bootstrap文件里面呢?因为这是spring启动时优先级的问题,会首先加载bootstrap里面的配置信息。
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=mall-protal
说明:之所以需要配置 spring.application.name ,是因为它是构成 Nacos 配置管理 dataId字段的一部分。
-
创建相关配置文件
这里创建和我们的项目名一致的配置信息:
- spring cloud获取数据更加简单,我们直接使用
Value注解即可获取数据。
@RestController
public class NacosController {
@Value("${txt:false}")
private String txt;
@GetMapping("/txt")
public String get(){
return txt;
}
}
- 这个时候我们可以成功获取数据,但是当我们修改配置信息的时候,却不会自动刷新。这是因为我们需要通过 Spring Cloud 原生注解
@RefreshScope实现配置自动更新:
@RestController
@RefreshScope
public class NacosController {
@Value("${txt:false}")
private String txt;
@GetMapping("/txt")
public String get(){
return txt;
}
}
2.4 多环境配置管理
我们有时候会以不同环境来运行项目:
配置文件有以下方式创建:
application.yml : 存储一些不需要放在 Nacos Config 的配置
bootstrap.yml : 基础配置,配置Nacos Config 的基础配置
bootstrap-dev.yml : 环境参数,开发环境
bootstrap-test.yml :环境参数,测试环境
bootstrap-prod.yml : 环境参数,线上环境
那如何让不同环境的项目读取不同的配置文件呢?这个时候我们创建配置文件的时候需要注意以下规则:
在 Nacos Spring Cloud 中,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为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension来配置。目前只支持properties和yaml类型。
按照如上规则,我们重新创建两个环境的配置文件:
然后我们只需要在application.properties文件中指定那个环境即可,或者启动项目的时候添加相关参数也可。我这里直接指定的开发环境。
#指定环境
spring.profiles.active=dev
代码里面处理完之后,我们直接在nacos里面配置相关数据即可,这里分别创建生产环境和开发环境对应的配置。注意命名格式: p r e f i x − {prefix}- prefix−{spring.profiles.active}.${file-extension}
两个配置文件里面的内容:
txt=devtxt # 开发环境
txt=protxt # 生产环境
配置文件创建完成之后,我们只需要在代码中调用一下即可,然后通过spring.profiles.active=dev修改环境,查看数据是否变化。
@RestController
@RefreshScope
public class NacosController {
@Value("${txt:false}")
private String txt;
@GetMapping("/txt")
public String get(){
return txt;
}
}
3. 分类管理
Nacos有分类管理的操作。抛出三个概念,namespace(命令空间)、group(分组)、dataid。
dataid:Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此命名规则非强制。这个概念来自于官方文档,说人话就是配置文件的名字,相当于主键的作用
group(分组): Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。说人话,就是可以分组,不同的系统或微服务的配置文件可以放在一个组里。比如用户系统和订单系统的配置文件都可以放在同个组中。
命名空间(namespace): 用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
总的来说,namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
使用起来也很简单,我们直接在命令空间里面新建即可,可以是中文也可以是英文。
建完之后,可以发现添加配置的时候可以选择不同的环境。
我们可以在项目中指定使用命令空间的配置信息:
#指定命名空间 id为对应的命令空间ID
spring.cloud.nacos.config.namespace=06aefa61-699b-485d-9ce6-c803fbfa21d4
#指定group
spring.cloud.nacos.config.group=DEFAULT_GROUP
指定完成之后就会读取指定命名空间下的配置信息。
4. 拓展配置和共享配置
当然,对于多个服务之间,可能会存在一些共享的配置,比如公用的日志信息,连接池信息等。如下图所示:
用法比较简单,该配置是一个数组,可以配置多个配置项,配置方法如下所示:
#拓展配置项 可以配置多个
#spring.cloud.nacos.config.extension-configs[0].data-id=log.yaml
#spring.cloud.nacos.config.extension-configs[0].refresh=true
#spring.cloud.nacos.config.extension-configs[1].data-id=test.yaml
#spring.cloud.nacos.config.extension-configs[1].refresh=true
#共享配置项 可以配置多个
#spring.cloud.nacos.config.shared-configs[0].data-id=log.yaml
#spring.cloud.nacos.config.shared-configs[0].refresh=true
#spring.cloud.nacos.config.shared-configs[1].data-id=test.yaml
#spring.cloud.nacos.config.shared-configs[1].refresh=true
5. 配置优先级
nacos 的配置信息会按照优先级进行加载:
- p r e f i x − {prefix}- prefix−{spring.profiles.active}.${file-extension}
- extension-configs(排序优先级)
- shared-configs(排序优先级)