目录
一、为什么需要配置中心
二、常用的配置中心
Nacos 的几个概念
三、Nacos配置中心的使用
(一)properties格式
(二)yaml格式
(三)profiles.active—粒度配置
(四)命名空间划分配置中心
(五)分组隔离
(六)自定义扩展的 Data Id 配置(共享配置)
(七)优先级
(八)动态配置刷新
常见报错
在没有配置中心之前,传统应用配置的存在以下痛点:
(1)采用本地静态配置,无法保证实时性:修改配置不灵活且需要经过较长的测试发布周期,无法尽快通知到客户端,还有些配置对实时性要求很高,比方说主备切换配置或者碰上故障需要修改配置,这时通过传统的静态配置或者重新发布的方式去配置,那么响应速度是非常慢的,业务风险非常大
(2)易引发生产事故:比如在发布的时候,容易将测试环境的配置带到生产上,引发生产事故。
(3)配置散乱且格式不标准:有的用properties格式,有的用xml格式,还有的存DB,团队倾向自造轮子,做法五花八门。
(4)配置缺乏安全审计、版本控制、配置权限控制功能:谁?在什么时间?修改了什么配置?无从追溯,出了问题也无法及时回滚到上一个版本;无法对配置的变更发布进行认证授权,所有人都能修改和发布配置。
而配置中心区别于传统的配置信息分散到系统各个角落的方式,对系统中的配置文件进行集中统一管理,而不需要逐一对单个的服务器进行管理。那这样做有什么好处呢?
(1)通过格式统一化配置中心,可以使得配置标准化、
(2)当配置信息发生变动时,修改实时生效,无需要重新重启服务器,就能够自动感知相应的变化,并将新的变化统一发送到相应程序上,快速响应变化。比方说某个功能只是针对某个地区用户,还有某个功能只在大促的时段开放,使用配置中心后只需要相关人员在配置中心动态去调整参数,就基本上可以实时或准实时去调整相关对应的业务。
(3)通过审计功能还可以追溯问题
微服务中配置中心的主流解决方案主要有三种:Nacos、Apollo、Config+Bus,不过里我们主要介绍 Nacos 作为配置中心的用法。
命名空间(Namespace)
命名空间可用于进行不同环境的配置隔离。一般一个环境划分到一个命名空间
配置分组(Group)
配置分组用于将不同的服务可以归类到同一分组。一般将一个项目的配置分到一组
配置集(Data ID)
在系统中,一个配置文件通常就是一个配置集。一般微服务的配置就是一个配置集
使用nacos作为配置中心,其实就是将nacos当做一个服务端,将各个微服务看成是客户端,我们将各个微服务的配置文件统一存放在nacos上,然后各个微服务从nacos上拉取配置即可。
就相当于服务模块请求nacos,nacos响应给服务模块一些数据
1、导入依赖
哪个服务模块要获取nacos配置管理的数据,就在哪个模块上添加依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
org.springframework.cloud
spring-cloud-starter-bootstrap
2、在配置中心新建配置
3、修改配置文件名为bootstrap.yml
4、在微服务中添加nacos config服务地址的配置
spring:
application:
name: user-server #注册服务的名称
# 配置数据源
datasource:
druid:
url: jdbc:mysql://localhost:3306/nacos?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
#clout配置nacos服务注册中心
cloud:
nacos:
discovery: #配置客户端
server-addr: 192.168.100.129:8848 #虚拟机ip地址和端口号
username: nacos #nacos网址的账号密码
password: nacos
#配置nacos网站的config配置中心
config:
server-addr: 192.168.100.129:8848 #虚拟机ip地址和端口号
file-extension: properties #配置内容的类型格式
username: nacos #nacos网站的账号密码
password: nacos
5、测试获取注册中心的配置
@RestController
@RequestMapping("/user")
public class UserController {
@Value("${username}")//通过配置中心的配置内容的键获取value
public String username;
@Value("${age}")//通过配置中心的配置内容的键获取value
public String age;
@GetMapping("/test2")
public void test2(){
System.out.println(username); //控制台打印张三
System.out.println(age);//99
}
}
6、可以将yml配置文件中数据库的配置移至配置中心,并修改工程中数据源的配置
在user服务模块中获取配置中心的配置内容数据源配置,这样也可以把数据库配置成功,就可以把yml配置文件中的数据源配置删除了
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.druid.username}")
private String username;
@Value("${spring.datasource.druid.password}")
private String password;
@Value("${spring.datasource.druid.url}")
private String url;
@Value("${spring.datasource.druid.driver-class-name}")
private String driverClassName;
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setDriverClassName(driverClassName);
return druidDataSource;
}
}
1、配置中心新建配置
Data Id:服务名.yaml
2、修改工程配置文件名为bootstrap.yml并修改配置文件配置
1、配置中心创建配置
data id : 服务名-profiles.后缀名(order-server-dev.yaml)
2、工程模块配置
1、创建命名空间
2、在对应命名空间下创建配置
3、工程模块配置命名空间
Namespace: 根据自己业务场景做好多环境配置隔离
Group:不同业务配置隔离
Group 也可以实现环境隔离的功能,但 Group 设计的目的主要是做同一个环境中的不同服务分组,把不同的微服务的配置文件划分到同一个分组里面去,Nacos 如果不指定 Group,则默认的分组是 DEFAULT_GROUP。
如果没有 Group,试想一下这个场景:有两个微服务,一个是订单系统,一个是用户系统,但是他们有着相同的配置,比如 datasource-url,那么如何区分呢?这时候 Group 就派上用场了。上述场景中订单系统、用户系统可以单独分为一个组,比如 ORDER_GROUP、USER_GROUP,当然这是比较细粒度的分组,根据企业的业务也可以多个微服务分为一组。 接下来我们演示一下创建配置集时以及集成时如何指定分组,还是前面的例子,新建配置集是在如下位置指定Group分组:
共享配置简介
简单来说就是哪个服务模块都可以获取共享配置
当我们微服务的数量越来越多,势必会有相同的配置,这时我们可以将相同的配置抽取出来作为项目中共有的配置,放在配置中心共享,每个服务都可以获取,比如集群中的数据源信息、日志的配置信息,nacos 也是支持这种一个配置中心多个配置集这种写法的。
细节提示
提示1、:多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.extension-config[n].data-id 其中 n 的值越大,优先级越高。
提示2、:extension-config[n]的优先级大于shared-configs[n],如果extension-config[n]有多个下标,他会先自己的下标走完,才会走shared-configs[n]的
提示3、:优先级越大会先执行,如果有重复的键会使用优先级较高的value,后执行的不会把先执行的数据覆盖掉
提示4、:spring.cloud.nacos.config.extension-config[n].data-id 的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。
案例演示:
1、在nacos中新建三个 Data ID 分别是 db.yaml 和 redis.yaml 和 MySQL.yaml 的文件。
2、在配置文件中分别加入部分配置内容
3、在 Springboot 项目中添加如下的 nacos 配置:
spring:
application:
name: user-server #注册服务的名称
#clout配置nacos服务注册中心
cloud:
nacos:
discovery: #配置客户端
server-addr: 192.168.100.129:8848 #虚拟机ip地址和端口号
username: nacos #nacos网址的账号密码
password: nacos
#配置nacos网站的配置中心
config:
#应用配置
server-addr: 192.168.100.129:8848 #虚拟机ip地址和端口号,config服务地址的配置
#file-extension: yaml #配置内容的类型格式
#namespace: fe4f886f-792a-4566-aff7-8ac8852e1aa9 #获取以dev命名空间划分的配置,value是dev开发的命名空间的id,默认public不需要写
#group: group1 #获取以group1分组的配置,默认DEFAULT_GROUP不需要写
username: nacos #nacos网址的账号密码
password: nacos
#共享配置,两种方式:extension的优先级大于shared,下标越大优先级越大
#如果extension-config[n]有多个下标,他会先自己的下标走完,才会走shared-configs[n]的
#优先级越大会先执行,如果有重复的键会使用优先级较高的value
extension-configs[0]:
data-id: db.yaml #指定配置中心的data id
#namespace: fe4f886f-792a-4566-aff7-8ac8852e1aa9 #获取以dev命名空间划分的配置,value是dev开发的命名空间的id,默认public不需要写
#group: group1 #获取以group1分组的配置,默认DEFAULT_GROUP不需要写
refresh: true #是否动态刷新,默认为false,为true时:如果db.yaml配置的内容发生了改变,在发送一次请求,就会动态刷新数据
extension-configs[1]:
data-id: redis.yaml#指定配置中心的data id
shared-configs[0]:
data-id: MySQL.yaml#指定配置中心的data id
4、测试,获取注册中心的配置
@RestController
@RequestMapping("/user")
@RefreshScope//只需要在需要动态读取配置的类上添加此注解就可以
public class UserController {
@Autowired
private OrderFeign orderFeign;
@Value("${username}")//通过配置中心的配置内容的键获取value
public String username;
@Value("${age}")//通过配置中心的配置内容的键获取value
public String age;
@Value("${sex}")//通过配置中心的配置内容的键获取value
public String sex;
@Value("${name}")//通过配置中心的配置内容的键获取value
public String name;
@Value("${phone}")//通过配置中心的配置内容的键获取value
public String phone;
@Value("${count}")//通过配置中心的配置内容的键获取value
public String count;
@GetMapping("/test2")
public void test2(){
System.out.println(username);
System.out.println(age);
System.out.println(sex);
System.out.println(name);
System.out.println(phone);
System.out.println(count);
}
}
访问地址
控制台打印
执行顺序:redis.yaml --> db.yaml --> MySQL.yaml
Nacos Config 目前提供了三种配置能力从 Nacos配置中心 拉取相关的配置
A: 共享配置:通过 spring.cloud.nacos.config.shared-configs[0].dataids 支持多个共享 Data Id 的配置
B: 共享配置:通过 spring.cloud.nacos.config.extension-configs[0].data-id 的方式支持多个扩展 Data Id 的配置
C: 应用配置: 服务名(user-server).yaml
D:粒度配置:应用名+ Profile user-server-dev.yaml
若三种配置同时使用,优先级由高到低依次为: D -→ C -→ B -→ A
配置文件优先级(由高到低):
bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml
在入门案例中,我们实现了配置的远程存放,但是此时如果修改了配置,我们的程序是无法读取到的,还得在重新启动服务,再次请求才会获取到更改的数据的,因此,我们需要开启配置的动态刷新功能,不需要重新启动服务,重新请求一次就行了。、
方式一: 硬编码方式
@RestController
public class NacosConfigController {
@Autowired
private ConfigurableApplicationContext applicationContext;
@GetMapping("/nacos-config-test1")
public String nacosConfingTest1() {
return applicationContext.getEnvironment().getProperty("config.appName");
}
}
方式二: 注解方式(推荐)
@RefreshScope 只需要在需要动态读取配置的类上添加此注解就可以
@RestController
@RequestMapping("/user")
@RefreshScope//只需要在需要动态读取配置的类上添加此注解就可以
public class UserController {
@Value("${name}")//通过配置中心的配置内容的键获取value
public String name;
@GetMapping("/test4")
public String test4(){
return name;
}
}
测试
因为我把动态刷新配置在db.yaml的配置文件中了,所以以db.yaml配置文件做测试
第一次发送请求name是李四
在db.yaml的配置文件中更改name
在一次发送请求,因为db.yaml的配置文件配置了动态刷新,不需要在重新启动服务更新数据,只需要再次发送请求就可以获取到更新后的数据了
1、如果启动不了报错,有可能出现的问题是:防火墙没有关闭,关闭防火墙后再去开启Nacos服务
查看防火状态
systemctl status firewalld
systemctl stop firewalld
然后再去启动Nacos服务
2、如果启动成功了,发现nacos服务注册中心网站没有任何数据和注册的消息,有可能是本机的网络更改了
因为conf/application.properties文件中IP地址是当前网络属性的IPv4地址,如果更换了网络要修改IP地址
# 启用standalone模式
nacos.standalone=true
# 修改端口号
server.port=8848
# 修改数据存储位置
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.216.176:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
注意要修改以下参数:
server.port:修改为要使用的端口号 db.url.0:修改为MySQL数据库的连接地址,IP地址是当前网络属性的IPv4地址,换一个网络会发生变化,记得修改
db.user、db.password:并设置正确的数据库用户名和密码
3、java.util.concurrent.TimeoutException:Linux代表没有启动nacos,记得关防火墙在启动
4、org.springframework.beans.factory.BeanCreationException:@Value没有注入成功,要仔细检查一遍有没有写错