继上一篇 微服务系列:Spring Cloud Alibaba 之 Nacos 注册中心 学习之后,今天我们来学习 Nacos
的另一个重要特性: 配置中心。
话不多说,开始今天的学习。
在微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移(分割),这样配置就分散了,不仅如此,分散中还包含着冗余,如下图:
总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。
传统的静态配置方式要想修改某个配置只能修改之后重新发布应用,要实现动态性,可以选择使用数据库,通过定时轮询访问数据库来感知配置的变化。轮询频率低感知配置变化的延时就长,轮询频率高,感知配置变化的延时就短,但比较损耗性能,需要在实时性和性能之间做折中。配置中心专门针对这个业务场景,兼顾实时性和一致性来管理动态配置。
配置的权限管控、灰度发布、版本管
理、格式检验和安全配置等一系列的配置管理相关的特性也是配置中心不可获取的一部分。
配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置。
3. Nacos 配置中心
Nacos
是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
配置中心的服务流程如下:
1、用户在配置中心更新配置信息。
2、服务A和服务B及时得到配置更新通知,从配置中心获取配置。
nacos
的下载方式和启动在上一篇 微服务系列:Spring Cloud Alibaba 之 Nacos 注册中心 文章中已描述,这里就不再赘述。
1、添加依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
2、在bootstrap.yml
添加Nacos配置
server:
port: 9201
# Spring
spring:
application:
# 应用名称
name: cloud-nacos-provider
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
注意是 bootstrap.yml
,
配置文件加载的优先级(由高到低)
bootstrap.properties ->bootstrap.yml -> application.properties -> application.yml
说明:之所以需要配置 spring.application.name
,是因为它是构成 Nacos 配置管理 dataId
字段的一部分。
在 Nacos Spring Cloud 中,dataId
的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}
prefix
默认为 spring.application.name
的值,也可以通过配置项 spring.cloud.nacos.config.prefix
来配置。spring.profiles.active
即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当 spring.profiles.active
为空时,对应的连接符 -
也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
,其实就算 spring.profiles.active
不为空,使用 ${prefix}.${file-extension}
同样可以找到对应配置。file-exetension
为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension
来配置。目前只支持 properties
和 yaml
类型。和同事一起开发项目的时候可以这样配置:
server:
port: 9211
# Spring
spring:
application:
# 应用名称
name: cloud-nacos-provider-ezhang # 此处后缀改成自己名字,防止和别人实例名一样出现负载均衡
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 配置文件前缀
prefix: cloud-nacos-provider
配上 spring.cloud.nacos.config.prefix
修改 spring.application.name
值为自己开发环境独有的,不和其他同事的实例名相同。但同时还需要在 gateway 网关中配置自己开发环境独有的路由
spring:
cloud:
gateway:
routes:
- id: cloud-nacos-provider-ezhang
uri: lb://cloud-nacos-provider-ezhang
predicates:
- Path=/ytb/**
3、在 nacos
控制台添加两个数据集(Data Id)
application-dev.yml
为共享配置cloud-nacos-provider-dev.yml
为私有配置4、编写测试类在Controller
类中通过@Value
注解获取配置值。
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${ezhang.useConfig:false}")
private boolean useConfig;
@Value("${version}")
private String version;
@RequestMapping("/get")
public String get() {
String str1 = "共享配置:" + useConfig;
String str2 = "私有配置:" + version;
return str1 + "," +str2;
}
}
5、浏览器访问:http://localhost:9201/config/get
返回正确数据表示测试通过。
相信你也注意到上面测试类中的 @RefreshScope
注解了,这个注解是 Spring Cloud 原生注解,是用来实现配置自动更新的。
测试类加上这个注解之后我们重新发布配置之后,就不用重启项目就可以自动更新了,当然,像是数据库连接这种的肯定还是需要重启项目的了。
我们改个配置试一下:
发布后重新访问地址 http://localhost:9201/config/get
配置已经自动更新了。
启动 Nacos
时我们可以看到这样一行日志:
Nacos started successfully in stand alone mode. use embedded storage
use embedded storage
表示使用的是内置数据源。
上面的这些配置都是存储在 Nacos
自带的嵌入式数据库中的,不方便观察数据存储的基本情况,所以在 0.7 版本增加了支持 MySQL
数据源能力,具体的操作步骤:
nacos-mysql.sql
conf/application.properties
文件,增加支持 mysql 数据源配置(目前只支持 MySQL ),添加 MySQL 数据源的 url、用户名和密码。spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=youdontknow
这个application.properties
和 nacos-mysql.sql
指nacos
的解压目录nacos/conf
目录下的文件
再以单机模式启动 Nacos,Nacos 所有写嵌入式数据库的数据都写到了 MySQL。
官方文档:https://nacos.io/zh-cn/docs/console-guide.html
这个直接查看官方文档就好了,官方文档讲的也挺清楚了。
Namespace + Group + DataId 三者关系
类似 Java 里面的 package 包名和类名,最外层的 Namespace 是可以用来区分部署环境的,Group 和 DataId 逻辑上区分两个目标对象。
默认情况
Namespace=public, Group=DEFAULT, 默认 Cluster 是 DEFAULT
Namespace
)1)什么是命名空间?
命名空间,即 Namespace,用于进行粗粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
举个贴切的例子:
一个超市,内部有很多区域,比如零售休闲区、瓜果蔬菜区、生鲜区等等,顺着超市路标指引,我们如果买鱼,直接去生鲜区即可,我们买零食,直接去零食休闲区即可,买个东西无需在超市乱窜…这种区域划分呢,便是物以类聚,环境隔离的思想。我们 Nacos 的 Namespace 思想就如同超市中不同大类型的划分区域。
Nacos
中存在一个默认的命名空间 public,所有配置以及服务注册,在没有指定命名空间时都会默认从 public 这个命名空间拉取配置以及注册到该命名空间下的注册表中。
可以看到,我们之前的服务注册列表以及配置列表都在这个默认的命名空间 public 下。
2)命名空间的使用
我们来新建两个环境的命名空间 dev 和 test
配置列表中就出现了两个 tab
我们把原来的配置克隆到新的命名空间下
然后需要我们在 bootstrap.yml
中配置一下使用的命名空间
server:
port: 9201
# Spring
spring:
application:
# 应用名称
name: cloud-nacos-provider
profiles:
# 环境配置
active: test
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
# 服务注册到哪个命名空间
namespace: 91e42ae4-9596-42fb-a24d-5d71aea068c9
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 服务从哪个命名空间拉取配置
namespace: 91e42ae4-9596-42fb-a24d-5d71aea068c9
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
增加 spring.cloud.nacos.discovery.namespace
和 spring.cloud.nacos.config.namespace
配置,值就是我们控制台创建时候生成的 命名空间id
我们这里是注册到了 test 命名空间下,启动项目会发现已成功注册。
test 命名空间下的 cloud-nacos-provider-test.yml
的配置如下:
还是访问我们之前的测试接口 http://localhost:9201/config/get
3)注意事项
Group
)Nacos 中的一组配置集(一个配置集就是一个配置文件),是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。
个人觉得 Group 类似于更细粒度一些的配置隔离。
举个通俗的例子:
我们还是用超市来举例,零食区中,薯片是放一个柜,糖是放一个柜;水产区,鲫鱼与鲫鱼是在一起的!基围虾和基围虾是放在一起的,这便是分组。
配置步骤和上面命名空间配置类似,就不详细写下了。
注意事项
Group+DataId
组合是唯一的,即同一分组下,不会出现多个相同 DataId 的配置;Group
间服务仍是隔离的,即服务注册到不同的分组时,无法使用 OpenFeign 指定服务名负载调用;Namespace+Group+DataId
组合是唯一的,即不同命名空间下可有相同分组以及相同DataId,但同一个命名空间下Group与DataId则是唯一的。PS:都看到这里了,点个赞吧,彦祖!