[TOC]java
为何要须要配置管理?git
在微服务架构中,每一个微服务都有可能会存在多个实例,为了保证同一微服务不一样实例的配置文件内容一致,咱们就须要有一个服务能够对微服务项目的配置文件进行统一管理,一般咱们将其称之为统一配置管理中心。由于若是配置文件的内容不一致,有可能会致使同一微服务的不一样实例在行为上发生差别,从而致使一些错误。github
除此以外,在企业开发中还要求项目在不一样环境使用不一样配置,以及能够在不重启服务的状况下实现配置文件的动态刷新,为了实现这些需求咱们也得使用到统一配置管理中心spring
目前业界比较流行的统一配置管理中心组件有Spring Cloud的Config、Spring Cloud Alibaba的Nacos以及携程开源的Apollo。本文主要介绍Nacos做为统一配置管理中心的使用,关于其余配置中心组件以及Nacos的基本使用能够参考以下文章:数据库
接下来,咱们看看如何使用Nacos管理配置文件,如今我有一段接口代码以下:json
@RestController @RequiredArgsConstructor public class TestController { @Value("${your.configuration}") private String yourConfiguration; @GetMapping("/getConfiguration") public String getConfiguration(){ return yourConfiguration; } }
这段代码读取了一个配置项,此时该配置项存在于项目的application.yml
文件中,以下:bootstrap
your: configuration: your_value
那么咱们要如何使用Nacos管理这段配置呢?首先须要为项目整合Nacos配置管理的功能,在pom.xml文件中添加以下依赖:windows
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
Greenwich.SR1
,Alibaba的版本为2.1.0.RELEASE
而后在resources
目录下新建一个名为bootstrap.yml
的文件,添加以下配置项:bash
spring: cloud: nacos: config: # 指定做为配置中心的nacos server地址 server-addr: 127.0.0.1:8848 # 配置文件格式 file-extension: yaml discovery: # 指定做为服务注册中心的nacos server地址 server-addr: 127.0.0.1:8848 application: name: content-center profiles: active: dev
到Nacos的管理页面的“配置列表”中新建配置:服务器
新建的配置内容以下图:
注意,这里的Data ID是具备必定格式的,须要与项目中的配置对应上。如上图中的:content-center-dev.yaml,其中content-center是微服务名称,dev是环境,yaml是配置文件的格式。这里简单整理成了一张对照图,以下:
.yaml
,也能够是.yml
,由于这两种后缀其实都是表示同一种文件格式到目前为止,咱们就已经为项目整合了Nacos的配置管理功能,并在Nacos Server上新建了项目所需的配置。此时就能够将以前配置在application.yml
文件中的配置项给删除掉。而后启动项目,访问/getConfiguration
接口,返回结果以下则表明整合成功:
在实际的企业开发中,咱们一般但愿在配置中心上修改了配置项后,不须要重启项目就可以实现实时的动态配置刷新。对于整合了Nacos的微服务项目来讲,想要实现这个功能是很简单的,只须要在读取了配置属性的类上加上@RefreshScope
注解便可。以下示例:
// 该注解用于标识哪些地方须要动态刷新配置,能够写在类及方法上 @RefreshScope @RestController @RequiredArgsConstructor public class TestController { @Value("${your.configuration}") private String yourConfiguration; @GetMapping("/getConfiguration") public String getConfiguration(){ return yourConfiguration; } }
添加完该注解后,重启项目,而后到Nacos上修改以前配置项的值,点击发布后会有一个内容比较的提示,能够看到我将以前的your_value
改为了my_value
:
点击确认发布后,而后再访问/getConfiguration
接口,返回的就是修改后的值了,而此时咱们并无重启项目:
除了以上所介绍的动态刷新以外,还有一个比较重要的功能:配置回滚。若是有一天修改某些配置项并发布后发现手滑改错了,致使项目运行出问题,那么就可使用回滚功能能够帮助我快速回滚到某个特定的版本上。咱们能够在Nacos的“历史版本”页面中查询指定配置的历史版本,以下图:
点击“详情”能够查看到具体的配置内容:
点击“回滚配置”则能够回滚到指定的历史版本,例如我这里就回滚到初始版本:
提示回滚成功后访问/getConfiguration
接口,会发现报错了:
这是目前Nacos 1.1版本的一个Bug,当选择回滚的版本是最第一版本时就会发生这个问题。官方称会在1.2版本中修复该问题,而我目前使用的是最新的1.1.3版本,仍属于1.1版本(2019-09-10),因此该bug还存在。相关的issues以下:
在1.1版本下,只要回滚的不是初始版本则不会触发这个bug,回滚其余版本是能够正常使用的,因此该问题注意一下便可规避
注:触发该bug后,配置内容因为回滚失败会丢失,此时须要从新建立配置
以上咱们介绍了Nacos做为配置中心的基本使用,而本小节将介绍相同应用下的配置共享,所谓的配置共享就是一些配置项能够在相同应用的不一样环境中进行共享。
例如以上示例中的${your.configuration}
配置项,咱们但愿在全部的环境下该配置项都是相同的值,而又不想在每一个环境的配置文件里面都配置一遍,也就是说这个配置项是全部环境通用的,那么这时候就须要将该配置项在全部环境中共享了。
想要实现配置共享只须要新建一个配置文件便可,首先咱们来看一段日志信息,当咱们启动项目时,控制台会出输出以下一段日志信息:
2019-09-11 20:47:42.197 INFO 13778 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='content-center-dev.yaml'}, NacosPropertySource {name='content-center.yaml'}]}
从该日志信息能够看到,项目在启动时会到Nacos上读取两个配置文件,即content-center-dev.yaml
和content-center.yaml
,其中content-center-dev.yaml
里保存的是开发环境下特定的配置,而content-center.yaml
里保存的则是全部环境下通用的配置。项目在启动时具体读取哪一个环境的配置文件是由bootstrap.yml
文件中的spring.profiles.active
配置项所决定的。
既然咱们知道保存在content-center.yaml
里的配置项会在全部环境中共享,那么只须要到Nacos上新建这个配置文件便可。以下示例:
新建完成后,修改项目中的spring.profiles.active
为其余环境,而后重启项目,此时访问/getConfiguration
接口,能够看到返回的是通用配置文件里所配置的值:
${your.configuration}
配置项同时存在于content-center-dev.yaml
和content-center.yaml
中,若spring.profiles.active
的值为dev
,那么读取的将是content-center-dev.yaml
里所配置的值。以上介绍了相同应用在不一样环境下的配置共享,但如何实现不一样应用之间的配置共享呢?例如咱们常常会遇到微服务A和微服务B的数据库配置是同样的,若是能将这段相同的配置在这两个服务之间共享,那么就能够省去一些重复的工做。
目前Nacos提供了两种方式能够实现不一样应用之间的配置共享,第一种方式是使用shared-dataids
。接下来咱们进行一个简单的演示,首先须要到Nacos上建立一些共享配置,以下示例:
其中common1.yaml
配置内容以下:
common1: configuration1: common1_value
common2.yaml
配置内容以下:
common2: configuration2: common2_value
建立共享配置完成后,修改项目中的bootstrap.yml
文件以下:
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: # 指定共享配置的DataId,多个使用,分隔 # 越靠后,优先级越高;common2.yml > common1.yaml # .yaml后缀不能少,目前只支持yaml/properties shared-dataids: common1.yaml,common2.yaml # 指定哪些共享配置支持动态刷新,多个使用,分隔 refreshable-dataids: common1.yaml server-addr: 127.0.0.1:8848 file-extension: yaml application: name: content-center profiles: active: dev
从以上的配置示例能够看出,其实shared-dataids
的主要做用就是用来指定共享配置的Data ID,使得该微服务能够读取这些共享配置。同理,其余微服务若想读取这些共享配置,只需在项目的bootstrap.yml
文件中添加相应的shared-dataids
配置便可,如此一来就实现了多个微服务之间的配置共享。
而后咱们来写两个简单的接口验证一下是否能正常读取这两个共享配置的值,代码以下:
@RefreshScope @RestController @RequiredArgsConstructor public class TestController { @Value("${common1.configuration1}") private String common1Configuration; @Value("${common2.configuration2}") private String common2Configuration; @GetMapping("/getCommonConfiguration1") public String getCommonConfiguration1() { return common1Configuration; } @GetMapping("/getCommonConfiguration2") public String getCommonConfiguration2() { return common2Configuration; } }
启动项目,访问结果以下:
第二种方式也是差很少的,只不过使用的配置项是ext-config
,修改项目中的bootstrap.yml
文件以下:
spring: cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yaml ext-config: # 需共享的DataId,yaml后缀不能少,目前只支持yaml/properties # 越靠后,优先级越高 优先级common2.yaml > common1.yaml - data-id: common1.yaml # common1.yaml所在的group group: DEFAULT_GROUP # 是否容许刷新,默认false refresh: true - data-id: common2.yaml group: DEFAULT_GROUP refresh: true application: name: content-center profiles: active: dev
ext-config
提供了较为细化的配置方式,而且能够指定配置组。到目前为止,咱们介绍了三种从Nacos上读取配置的方式,其优先级以下:
shared-dataids < ext-config < 自动
除此以外,当存在相同的远程配置和本地配置时,远程配置优先级要高于本地配置文件。但能够经过添加以下配置调整,须要注意的是这段配置须要放在远程配置才会生效:
spring: cloud: config: # 是否容许本地配置覆盖远程配置,默认true allow-override: true # 是否一切以本地配置为准,默认false override-none: false # 系统环境变量或系统属性才能覆盖远程配置文件的配置 # 本地配置文件中配置的优先级低于远程配置,默认true override-system-properties: true
在介绍为项目整合Nacos作配置管理服务的时候,示例里将Nacos Config的相关配置都写在一个bootstrap.yml
文件里,可是为何要使用bootstrap.yml
呢?使用application.yml
不能够吗?
这是实际上是由于bootstrap.yml
会被优先读取,也就是说若是项目里同时存在一个bootstrap.yml
和一个application.yml
的话,那么bootstrap.yml
将会优先于application.yml
被Spring Boot读取。这样才能实现链接外部的配置管理服务器,从远程读取一些必要的配置,避免项目在启动时缺失必要配置项而致使启动失败。
这里实际涉及到一个引导上下文的概念,它是ApplicationContext
的父上下文,而且是由Spring Cloud提供的, 它所在的位置以下图所示:
引导上下文在prepareEnvironment
的阶段就会被建立,建立时会读取bootstrap.yml
的内容做为引导配置, 所以bootstrap.yml
优先于application.yml
加载。引导上下文与操做系统的引导程序很是相似,而bootstrap.yml
就至关于设置引导程序的相关指令。
Nacos会将数据持久化到本地,当Nacos做为服务发现组件时,默认会将服务的注册信息存储在以下目录中:
类Unix系统:~/nacos/naming windows系统:C:\用户\{用户名}\nacos\naming
具体文件以下图所示:
打开其中一个文件,能够看到服务注册信息的格式以下:
{ "metadata": {}, "dom": "DEFAULT_GROUP@@content-center", "cacheMillis": 10000, "useSpecifiedURL": false, "hosts": [], "name": "DEFAULT_GROUP@@content-center", "checksum": "f797b857f5312a616a875924ecf6481a", "lastRefTime": 1564815242804, "env": "", "clusters": "" }
当Nacos做为配置中心时,配置数据会分为两份并存储在两个地方,其中一份存储在内嵌的derby数据库中,这是Apache开源的一个彻底由Java编写的内嵌数据库,而derby会有一个数据目录,以下:
$NACOS_HOME/data/derby-data
咱们可使用IDEA链接derby来查看相关的数据表及存储内容,在右边菜单栏中点开Database -> 点击+符号添加数据库链接 -> Data Source -> Apache Derby。以下图所示:
注意,此时须要将Nacos Server给中止掉,不然是没法链接的。中止Nacos Server以后,填写相关的链接信息,Path填的是derby的数据目录,用户和密码默认都是nacos。以下图所示:
链接成功后,能够看到derby中的数据表以下:
其中CONFIG_INFO
表存储了配置数据,打开该表能够看到内容以下:
须要注意的是derby并不能用于生产环境,由于它是一个内嵌数据库,没法实现高可用和集群部署,因此通常搭建生产可用的Nacos时会将数据库改成使用MySQL等非内嵌数据库。
而另外一份数据存储在以下目录,主要是一些快照等数据:
类Unix系统:~/nacos/config windows系统:C:\用户\{用户名}\nacos\config
快照主要用于提高性能以及作容灾备份,具体文件以下图所示: