在企业项目中会有非常多的服务,不同的开发环境还有不同的配置文件,所以就导致配置文件非常多。
那么肯定就会有一些公共配置,多个服务都是使用过一样的,那么就可以使用配置中心来进行统一管理,避免修改一个配置项要去各个服务都改一遍。
使用传统方式的配置文件弊端:
维护性,修改一个配置项,需要对多个服务的这个配置都进行修改
时效性,修改完配置文件,必须对服务进行重启,一个服务搭建了集群,现在仅仅重启了第一个服务实例,其他的还没有重启,就造成了配置不一致
安全性,重要的配置项,比如密码直接写在配置文件中,不太安全
Nacos配置中心,它可以对公共的配置文件进行管理,可以直接在配置中心进行修改,然后各个服务就能动态的感知到。nacos配置中心还可以对不同的命名空间设置角色,并授权读写权限。
市面上常见的配置中心:Spring Cloud Config 、apollo、nacos
首先是配置列表,这里会维护配置中心当中所有的配置文件,然后就可以在微服务当中引入我们对应的配置文件了
首先创建一个配置文件
Data ID我们可以理解为配置文件的名称,官方推荐了一种命名规则,采用类java包(如com.taobao.tc.refund.log.level)的命名规则保证全局唯一性,当然命名规则非强制。
Group是在命名空间的基础上,再进行一个细粒度的分类,比如命名空间可以使用dev、sit环境来进行分类,然后分组中使用各个项目来进行分类
其实新建的这个配置文件是存储在nacos数据库中config_info
数据表中。
配置列表中就有了我们刚刚创建的配置文件了,点击右边的详情可以查看操作,点击编辑可以进行修改操作
还可以点击更多 --> 历史版本,来查看该配置文件历史修改,比如我现在对该配置文件进行了一个修改操作,然后查看历史版本,就会发现这里有两条记录,一条是最刚开始的创建记录,还有一条就是各个的修改操作,我们可以点击回滚按钮,回滚到这一个修改前的配置文件内容,点击详情也是查看修改前的内容。
还可以点击更多 --> 监听查询来查询nacos有没有将配置推送至客户端。
其他的一些配置
然后选择目标命名空间
权限管理
之前提过Nacos也有针对安全性问题的相关功能,就是权限管理,给特定的角色赋予不同命名空间的读写权限。
如果要使用权限控制,必须修改conf/application.properties
配置文件中的nacos.core.auth.enabled=true
,权限控制的功能才会起作用。
首先在用户列表创建一个用户
第二步给刚刚创建的用户绑定角色,角色名如果不存在则会创建一个。
第三步,权限管理
现在登录该用户,查看其他命名空间就没有权限了
我们一旦修改了配置中心的配置文件,客户端能够实时的感受到。
这是现在配置中心中的文件内容
创建一个nacos-config
的服务,创建主启动类
首先需要在服务中添加依赖
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
dependencies>
编写yml配置文件,必须创建bootstrap.yml
或者bootstrap.properties
文件,然后在其中指定Nacos相关的配置
spring:
application:
# 指定服务名,会自动根据服务名拉取配置文件中Data id对应的配置文件,如果服务名和Data id不一致就需要手动指定Data id了
name: com.springcloudAlibaba.order.redis
cloud:
nacos:
server-addr: 127.0.0.1:8848 # 指定Nacos Server的ip和端口
# 指定用户名和密码,如果我们在Nacos Server的配置文件中开启了权限nacos.core.auth.enabled=true就一定要添加用户名密码
username: nacos
password: nacos
# 指定命名空间,这个nacos config的一个bug
# 当我们指定命名空间为public时,启动后就会不停的在控制台进行输出,默认也是public,所以就不要指定下面的两行了
# 这是因为nacos Client每10ms根据文件的MD5去配置中心进行判断,拉取最新的配置文件
#config:
#namespace: public
编写主方法进行测试
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);
System.out.println("姓名:" + applicationContext.getEnvironment().getProperty("user.name"));
System.out.println("年龄:" + applicationContext.getEnvironment().getProperty("user.age"));
}
}
结果为:
测试修改了配置中心的配置文件,客户端动态的感知
主方法中改为一个死循环
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);
while (true) {
System.out.println("姓名:" + applicationContext.getEnvironment().getProperty("user.name"));
System.out.println("年龄:" + applicationContext.getEnvironment().getProperty("user.age"));
Thread.sleep(1000);
}
}
}
当我修改配置文件的内容为:
结果为:
# 处了配置中心的配置,其他的配置都可以写在application.yml文件中,包括下面的服务名也可以写在application.yml文件中
spring:
application:
name: com.springcloudAlibaba.order.redis # 指定服务名,会自动根据服务名拉取配置文件中Data id对应的配置文件
cloud:
nacos:
# 指定Nacos Server的ip和端口
server-addr: 127.0.0.1:8848
# 指定用户名和密码,如果我们在Nacos Server的配置文件中开启了权限nacos.core.auth.enabled=true就一定要添加用户名密码
username: nacos
password: nacos
config:
# 指定配置中心中配置文件的格式,默认值是properties
file-extension: yaml
#refresh-enabled: false 关闭nacos客户端动态感知配置中心修改的内容
# 指定命名空间
namespace: bbdd0fc6-30af-4402-ab41-759c3e25138d
# 指定分组,默认值是DEFAULT_GROUP
group: cms
# 引入特定的Data id
shared-configs:
- dataId: com.springcloudAlibaba.common.properties
group: DEFAULT_GROUP
refresh: true # nacos客户端动态感知配置中心的修改 默认的关闭的
- dataId: com.springcloudAlibaba.common2.properties
group: DEFAULT_GROUP
refresh: true
extension-configs[0]:
dataId: com.springcloudAlibaba.common3.properties
group: DEFAULT_GROUP
refresh: true
extension-configs[1]:
dataId: com.springcloudAlibaba.common4.properties
group: DEFAULT_GROUP
refresh: true
文件扩展名配置方式
文件扩展名指的就是配置中心中文件的配置格式
nacos 客户端默认情况下是读取的properties,如果我们修改了配置中心文件的格式,就必须要在Nacos Config Client进行相应的配置,比如我现在将配置格式改为yaml
那么nacos客户端就需要指定:
spring:
cloud:
nacos:
config:
# 指定配置中心中配置文件的格式,默认值是properties
file-extension: yaml
这个仅仅针对默认的配置文件,如果直接引入特定的配置文件,该配置文件的类型可以和这里设置的不一样
配置的动态更新
就是如果配置中心进行了更新,nacos客户端能够动态的感知。默认是开启的,如果不想让nacos客户端动态更新可以使用以下配置关闭
spring.cloud.nacos.config.refresh-enabled=false
支持profile粒度的配置
nacos客户端在启动时,不仅仅加载了Data id为${spring.application.name}
的配置文件,同时还会加载以下两个配置文件:
${spring.application.name}.${spring.cloud.nacos.config.file-extension}
服务名.文件后缀
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
服务名-环境.文件后缀
也就是说,只有默认的配置文件才支持profile粒度的配置,默认的配置文件就是指Data id和服务名相同。
注意:
${spring.cloud.nacos.config.file-extension}
指定的一致,否则读取不到服务名 < 服务名.文件后缀 < 服务名-环境.文件后缀
.文件后缀
推荐还是不使用profile方式来做环境的分割,推荐使用命名空间来区分不同的开发环境,因为这样就可以使用nacos的权限管理。
命名空间namaspace配置
nacos客户端默认使用的命名空间是public,我们可以在nacos服务端自定义命名空间,然后在nacos客户端进行指定
spring.cloud.nacos.config.namespace=bbdd0fc6-30af-4402-ab41-759c3e25138d
注意,这里的值需要指定命名空间的id,
group组配置
还可以在命名空间下使用分组进行更加细粒度的拆分,推荐使用下图对应的来进行拆分命名空间与组
nacos客户端的配置是:
# 指定分组,默认值是DEFAULT_GROUP
spring.cloud.nacos.config.group=组名
指定自定义Data id 配置
很多时候我们还会引入一些其他的配置文件,就不能使用服务名来引入默认的配置文件了。这个时候就需要指定Data id
有两种方式,extension-configs
和 shared-configs
,这两种方式的参数都是数组,使用方法一样,唯一的区别就是优先级的区别
优先级 : 默认配置文件
> extension-configs(下标越大优先级越高)
> shared-configs(下标越大优先级越高)
先使用shared-configs
spring:
cloud:
nacos:
config:
# 引入特定的Data id
shared-configs:
- dataId: com.springcloudAlibaba.common.properties
group: DEFAULT_GROUP
refresh: true # nacos客户端动态感知配置中心的修改 默认的关闭的
当然也可以指定多个,因为是数组 yaml文件有两种表示数组的方式:- 或者是数组下标
spring:
cloud:
nacos:
config:
# 引入特定的Data id
shared-configs:
- dataId: com.springcloudAlibaba.common.properties
group: DEFAULT_GROUP
refresh: true # nacos客户端动态感知配置中心的修改 默认的关闭的
- dataId: com.springcloudAlibaba.common2.properties
group: DEFAULT_GROUP
refresh: true
如果通过数组 引入了多个配置文件,这其中如果有重复的配置项,那么是采用最下方的,也就是说之后引用的配置会替换之前引用的
接下来就是extension-configs
,这里我就采用数组下标的方式演示
# 处了配置中心的配置,其他的配置都可以写在application.yml文件中,包括下面的服务名也可以写在application.yml文件中
spring:
cloud:
nacos:
config:
# 引入特定的Data id
shared-configs:
- dataId: com.springcloudAlibaba.common.properties
group: DEFAULT_GROUP
refresh: true # nacos客户端动态感知配置中心的修改 默认的关闭的
- dataId: com.springcloudAlibaba.common2.properties
group: DEFAULT_GROUP
refresh: true
extension-configs[0]:
dataId: com.springcloudAlibaba.common3.properties
group: DEFAULT_GROUP
refresh: true
extension-configs[1]:
dataId: com.springcloudAlibaba.common4.properties
group: DEFAULT_GROUP
refresh: true
因为
优先级 : 默认配置文件
> extension-configs(下标越大优先级越高)
> shared-configs(下标越大优先级越高)
所以一般一些公共的配置文件就使用优先级最低的shared-configs来引入,
@RefreshScope注解动态更新@Value的值
@Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,可以在类上面加上@RefreshScope
注解来动态感知
package com.hs.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/test")
@RestController
@RefreshScope
public class TestController {
@Value("${user.name}")
private String username;
@Value("${user.age}")
private String age;
@RequestMapping("test1")
public String test1(){
System.out.println(username);
return "用户名:" + username + ",age:" + age;
}
}