实现配置中心
写在前面
在前面分析Nacos的pom.xml
依赖文件时,我们发现Nacos不仅支持Eureka的服务发现与注册外,还具有Ribbon的客户端负载均衡、Config的分布式配置等功能。那么本篇就来学习最后的一个功能,如何使用Nacos实现配置中心这一目的。
通过Nacos的配置管理,开发者可以将整个架构体系中的所有配置都集中在Nacos中进行存储。
快速入门
接下来将演示如何使用Nacos实现配置中心,主要包括如何在Nacos中创建配置内容和如何在Spring Cloud应用中加载Nacos配置中心的配置信息。
创建配置
请注意这里依旧不像之前在学习Spring Cloud Config实现配置中心时那样,需要先创建一个Spring Boot应用作为config-server,那是因为这里的Nacos既是一个“eureka-server”项目,还是一个“config-server”项目,因此配置中心服务端项目其实可以复用之前的nacos-server-1.3.1
,但是需要进行一些配置修改,如下所示:
第一步,启动Nacos服务端,点击左侧的配置管理—>配置列表,然后点击右上角的“+”按钮,进入“新建配置”页面,填写下图所示的内容:
解释一下上述参数的含义:
Data ID
,这个是服务配置文件的全称,格式为服务名.配置格式
,这里填入config-client.properties
;Group
,这里不修改,使用默认的组,值为DEFAULT_GROUP;配置格式
,一般是YAML或者Properties,笔者这里选择Properties;配置内容
,这个是应用需要加载的配置信息,也就是Data ID
文件中的内容,这里笔者设置了三条参数:看到这里你会发现这个和Spring Cloud Config不同,这里居然自己设置了应用的配置信息,然后运用直接就可以从它这里获取配置信息。而在Spring Cloud Config则是采用Git来存储配置信息,它需要用户配置Git仓库地址信息、用户信息,然后通过git clone命令将配置信息从Git仓库中复制一份在本地进行存储,然后读取这些内容并返回给微服务应用进行加载。1
2
3spring.application.name=config-client
server.port=8020
envythink=prod-1.0
创建应用
第一步,创建Spring Boot项目。使用Spring Initializr
工具创建一个Spring Boot应用,名称为config-client
,请注意这个名字尽量与之前的Data ID
保持一致。
第二步,编辑依赖文件。编辑项目的pom.xml依赖文件,添加如下配置信息:
1 | <parent> |
特别注意其中Spring Cloud、Spring Cloud Alibaba和Spring Boot这三者的版本信息,这个在前面已经介绍了。同时需要将之前使用的spring-cloud-starter-alibaba-nacos-discovery
依赖修改为spring-cloud-starter-alibaba-nacos-config
,这也就说明Nacos的服务注册与发现功能和配置中心这两个功能是可以独立使用的,需要使用什么功能就添加对应的依赖即可:
1 | <!--Nacos配置中心功能--> |
第三步,提供一个访问接口。由于这是一个web工程,因此可以添加一个Controller,并提供一个访问入口。在项目目录下新建controller包,并在里面新建HelloController文件,其中的代码为:
1 | @Slf4j |
关于上述代码,这里有几点需要引起注意:(1)先定义envythink这个属性,然后通过@Value
注解来绑定配置服务中配置的envythink属性;(2)除了通过使用@Value
注解来对属性进行绑定注入外,还可以使用Environment对象来获取配置属性,需要注意的是这个Environment对象存在于org.springframework.core.env.Environment
包内,导包不能出错;(3) 其中的@RefreshScope
注解用于实现配置和实例的刷新。
第四步,属性配置。在application.properties
配置文件同级目录下新建一个bootstrap.properties
文件(注意名字不能修改),然后在里面用于配置一些信息,用于获取配置文件config-client
的位置:
1 | spring.application.name=config-client |
请注意由于此处使用的是Nacos的配置中心功能,没有使用期服务注册与发现功能,因此这里使用spring.cloud.nacos.config.server-addr
参数来绑定Nacos配置中心地址。再次强调这里的配置文件名称必须为bootstrap.properties
,因为它的优先级高于application.properties
配置文件,且其中spring.application.name
必须是前面在Nacos配置中设置的Data Id
。
第五步,启动项目。首先确保之前下载的nacos服务已经正常运行,然后启动这里名为config-client
的服务,可以发现在其控制台输出如下信息:
1 | Located property source: [BootstrapPropertySource {name='bootstrapProperties-config-client.properties,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-config-client,DEFAULT_GROUP'}] |
也就是说这里会先读取之前我们在bootstrap.properties
启动文件中设置的信息,并后续通过这些参数来从Nacos配置中心获取配置信息。
第六步,验证配置获取和动态刷新。开发者最简单的验证方式就是直接打开浏览器访问http://localhost:8020/hello
,如果返回prod-1.0也就是之前在Nacos中配置的信息,说明已经可以获取到配置信息:
将下来直接修改Nacos配置中心的配置项,将其中envythink的值由prod-1.0修改为prod-111.0,之后点击发布,并再次访问该接口,可以看到返回信息发生了变化:
同时仔细观察config-client项目的输出控制台,发现已经出现提示envythink配置刷新的信息:
这样Nacos配置中心的基础入门学习就完成了,按照之前学习Spring Cloud Config的顺序,接下来应当是介绍Nacos服务端和客户端的相关配置。
服务端配置详解
尽管Nacos官方提供了Nacos服务端应用,但是这已经是打包好的程序,我们之前使用的都是默认配置,接下来就仿照学习zipkin-server时的情形,来根据一些环境参数来自定义服务端配置。
加载规则
在入门例子中,我们都是完全采用了默认的配置,那么在此种条件下Nacos是如何加载配置信息的呢?
之前我们在Nacos中创建的配置内容是这样的:
(1)Data ID
为config-client.properties
;
(2)Group
使用了默认的DEFAULT_GROUP;
(3)配置格式
选择Properties;
(4)配置内容
填写以下信息:
1 | spring.application.name=config-client |
接下来对上述配置内容进行拆分,这里主要涉及到三个参数,它们与具体应用的配置对应关系如下:
(1)Data ID
中的config-client
其实对应于客户端中spring.cloud.nacos.config.prefix
参数,其值默认为${spring.application.name}
,也就是服务名称;
(2)Data ID
中的properties
其实对应于客户端中spring.cloud.nacos.config.file-extension
参数,其值默认为properties;
(3)Group
其实对应于客户端中spring.cloud.nacos.config.group
参数,其值默认为DEFAULT_GROUP。
至于其中的配置格式
其实也就是(2)中的参数,配置内容
其实也就是配置文件中的内容。
接下来依旧使用之前的config-client项目,通过手动修改一些参数来演示这些参数的使用,并加深对上述参数与客户端之间的对应关系的理解与印象。
场景1:不通过服务名来加载,则是自定义名称,但是组依旧是使用DEFAULT_GROUP,那么就可以通过在客户端config-client项目的bootstrap.properties
启动文件中添加如下参数来实现:
1 | spring.cloud.nacos.config.prefix=config-client |
因为前面之所以配置spring.application.name
也能实现这个目的,那是因为spring.cloud.nacos.config.prefix
参数默认值为spring.application.name
的缘故,要知道其真正是通过上述参数来控制的。
场景2:不通过服务名来加载,自定义组名为ENVY_GROUP,此时仍可以通过在客户端config-client项目的bootstrap.properties启动文件中添加如下参数来实现:
1 | spring.cloud.nacos.config.prefix=config-client |
场景3:不通过服务名来加载,自定义组名为ENVY_GROUP,且使用YAML格式的配置文件,此时还此时还可以通过在客户端config-client项目的bootstrap.properties启动文件中添加如下参数来实现:
1 | spring.cloud.nacos.config.prefix=config-client |
其实上面这三个参数中场景1和场景3的参数配置没什么特殊,主要是场景2中组的设置有时候可以派上大用处,尤其是在公司产品线较多的情况下,可以解决同名应用的冲突问题,正常情况下都可以使用它来区分不同用途或者不同环境的配置。
多环境管理
其实Nacos本身就具有多个不同管理级别的概念,像之前学到的Data ID、Group和NameSpace等,既然讲到了Nacos可以实现多环境的配置,那么接下来就学习Nacos如何实现多环境的配置。
使用Data ID
配合profiles
来实现
其实这个Data ID
官方定义是配置集ID,而配置集是一组相关或者不相关的配置项的集合。在系统中,一个配置文件通常就是一个配置集,里面包含了系统各个方面的配置记录,如前面在创建配置时需要设置的几项参数,当然也可能包含数据源、线程池以及日志级别的配置项等信息。
那自然配置集ID就是用来唯一标识某个配置集,它是组织划分配置的一个维度。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID
通常采用类Java包(如 com.envy.tk.refund.log.level
)的命名规则来保证全局的唯一性。请注意此命名规则非强制,开发者可自定义设置。
在学习Spring Cloud Config服务端的配置一文中讲到,Config客户端应用启动时,会根据bootstrap.properties
配置文件中配置的应用名{ application }
、环境名{ profile }
、分支名{ label }
、Config Server地址等信息,向Config Server请求来获取配置信息。
既然Nacos底层使用了Config,那么也是具有类似的操作,只不过这些参数都是由Nacos配置中心来设置的。通过前面的学习,我们可以将Nacos中的Data ID理解为是一个Spring Cloud应用的配置文件名称,它默认的名称格式为:${spring.application.name}.properties
。
既然使用了Config,那么这个Data ID
的名称规则其实也应该包含逻辑,就像在Spring Cloud Config中使用spring.profiles.active
参数来指定具体的环境名称,因此这里的Data ID
其实就可以修改为${spring.application.name}-${spring.profiles.active}.properties
这一格式。如果把之前在加载规则中学到的3个参数也添加进来,并进行修改的话,那么此时Data ID
的完整格式如下所示:
1 | ${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
如果其中的${spring.cloud.nacos.config.prefix}
和${spring.cloud.nacos.config.file-extension}
都使用默认值,那么就变成了${spring.application.name}-${spring.profiles.active}.properties
,正常我们都使用后者。其实这也能体现出Spring Boot提倡的习惯优于配置这一设计理念。
前面说的都是理论知识,接下来将通过基于前面的例子实现的一个demo来演示Nacos如何多环境管理。
第一步,在Nacos中创建多环境配置。按照图示在Nacos中配置多环境,这里配置了三个环境:默认、TEST和PROD:
其中PROD环境的envythink值与之保持一致,且端口号为8021:
而TEST环境的envythink值也与之保持一致,且端口号为8022:
第二步,指定使用环境。在config-client客户端的bootstrap.properties
启动文件中指定要获取的环境,可以通过如下参数来实现:
1 | # Nacos多环境参数配置 |
请注意这里通过应用名称和使用环境组合来确定应该去Config配置中心查找获取和使用哪个配置文件来使用,其实得到就是 config-client-TEST.properties
文件中的内容。
第三步,启动项目并测试。首先确保之前下载的nacos服务已经正常运行,然后启动这里名为config-client的服务,并打开浏览器访问http://localhost:8022/hello
,如果返回TEST也就是之前在Nacos中配置的信息,说明已经可以获取到配置信息,且config-client服务是以config-client-TEST.properties
文件来启动的:
开发者甚至可以使用netstat -aon|findstr 8022
来查看端口的使用情况,这一点会更加证实上述结果。
当然也可以通过观察config-client项目的输出台信息来进行验证:
使用Group
实现
在前面我们提到过使用Group可以很容易解决Data ID
冲突的问题,其实如果把一个环境的配置看成一个组,那么对于多环境的配置管理不就转变成了对于组的管理么,这不就是Group
干的事么?其实这个Group
用起来非常灵活,针对不同的应用场景可以实现不同的目的,从架构运维角度可以认为是对多环境的管理;从业务角度可以认为是对不同模块的参数管理。不过这样容易产生冲突,因此在最初架构设计的时候,需要进行一定的规划和设计,不过这里先来学习如何使用Group
来实现从运维角度的多环境管理。
Group在官方文档中是配置分组,它也是组织配置的维度之一。开发者可以通过一个有意义的字符串来对配置集进行分组,从而区分Data ID
相同的配置集。前面也说了如果开发者未填写配置分组的名称,则配置分组的名称默认采用DEFAULT_GROUP,一般是在不同应用或组件使用了相同的配置类型的情况下才使用配置分组,如database_url
配置和MQ_topic
配置。
第一步,在Nacos中创建多GROUP组配置。按照图示在Nacos中配置多GROUP组,这里配置了三个GROUP组:DEFAULT_GROUP、TEST_GROUP和PROD_GROUP,请注意这三者的Data ID
完全是一样的,如下所示:
其中TEST_GROUP组的envythink值为test-group
,且端口号为8023:
其中PROD_GROUP组的envythink值为prod-group
,且端口号为8024:
第二步,指定使用环境。在config-client客户端的bootstrap.properties
启动文件中指定要获取的环境,可以通过如下参数来实现:
1 | # Nacos多环境参数配置 |
请注意这里通过应用名称和组名组合来确定应该去Config配置中心查找获取和使用哪个配置文件来使用,其实得到就是PROD_GROUP分组下的 config-client.properties
文件中的内容。
第三步,启动项目并测试。首先确保之前下载的nacos服务已经正常运行,然后启动这里名为config-client的服务,并打开浏览器访问http://localhost:8024/hello
,如果返回prod-group也就是之前在Nacos中配置的信息,说明已经可以获取到配置信息,且config-client服务是以PROD_GROUP分组下的config-client.properties
文件来启动的:
开发者甚至可以使用netstat -aon|findstr 8024
来查看端口的使用情况,这一点会更加证实上述结果。
当然也可以通过观察config-client项目的输出台信息来进行验证:
使用Namespace
实现
在前面我们提到了Data ID
和GROUP
,但是接下来即将学习的Namespace
应该是第一次接触的。
官方对于Namespace命名空间的定义是这样的,用于对租户粒度的配置隔离。租户粒度就意味这这个权限粒度很粗,甚至超出了之前两个的权限控制,也就是说在不同的命名空间下,可以存在相同的Group和Data ID
。Namespace命名空间的常用场景是针对不同环境的配置的区分隔离,如开发测试环境和生产环境的资源(如配置、服务)隔离等。更多参数的介绍可以点击 这里进行学习。
也就是说之前的Group尽管可以实现不同环境的管理,但是似乎使用这里的Namespace命名空间是更合适的。
第一步,在Nacos中创建多Namespace命令空间配置。按照图示在Nacos中配置多Namespace命令空间,这里配置了三个Namespace命令空间:默认的Public、TEST和PROD,如下所示:
其中Namespace命令空间为TEST的envythink值为test-namespace,且端口号为8025:
其中Namespace命令空间为PROD的envythink值为prod-namespace,且端口号为8026:
第二步,指定使用环境。在config-client客户端的bootstrap.properties
启动文件中指定要获取的环境,可以通过如下参数来实现:
1 | # Nacos多环境参数配置 |
请注意这里通过应用名称和命名空间组合来确定应该去Config配置中心查找获取和使用哪个配置文件来使用,注意spring.cloud.nacos.config.namespace
后面配置的是命名空间对应的ID,而不是命名空间的名称,这样得到就是名为TEST的命名空间下的 config-client.properties
文件中的内容:
第三步,启动项目并测试。首先确保之前下载的nacos服务已经正常运行,然后启动这里名为config-client的服务,并打开浏览器访问http://localhost:8025/hello
,如果返回test-namespace也就是之前在Nacos中配置的信息,说明已经可以获取到配置信息,且config-client服务是以命名空间为TEST下的config-client.properties
文件来启动的:
开发者甚至可以使用netstat -aon|findstr 8025
来查看端口的使用情况,这一点会更加证实上述结果。
当然也可以通过观察config-client项目的输出台信息来进行验证:
怎么选择
有时候解决办法多了,对于选择哪种解决办法也是一件非常令人头疼的事,尤其是具有选择困难症的处女座,当然我不是处女座,但是也是很烦的。笔者通过搜寻一些文章,这里将这三种方式实现的优劣势进行了汇总,这样大家可以在选择使用的时候进行参考。
第一种,通过Data ID
配合profiles
来实现。
- 优点:很显然与Spring Cloud Config的配置相似,因此熟悉Spring Cloud Config的童鞋可以无缝衔接,无需额外的学习;
- 缺点:当项目和环境都很多的时候,此时配置内容就会显得非常混乱,配置列表会显示各种不同类别,不同环境的应用。
- 使用建议:当项目和环境不多的时候使用,也可以结合Group来对项目依据业务或者组织架构进行划分管理。
第二种,通过Group
来实现。
- 优点:可以将各个应用的环境通过分组来进行管理,可以解决同名配置的问题,同时Group和
Data ID
是比较基础的数据,在创建配置时就可以设置,且后续可以通过Group和Data ID
来实现配置搜索功能; - 缺点:需要使用Group,因此前期需要对Group做好较为完善的规划,否则后续会产生比较大的问题。
- 使用建议:Group组规划的较为合理,应用分类不会出现重复的情况时可以使用,但是对于这个Group组的规划很难做到合理。
第三种,通过Namespace
命名空间来实现。
- 优点:这是三者中粒度最粗的控制,也就意味着允许存在相同的
Group
和Data ID
,这无疑更加适合多环境的场景。同时Namespace是分组显示,不需要使用搜索就可以隔离不同的环境配置; - 缺点:应该说目前没发现有什么较为大的缺点,非要说的话就是多了一个概念而已。
- 使用建议:优先选择此种方式,可以获得最大的效益。如果是应用和环境较少的情况下,使用前两种似乎也无可厚非,但是这种似乎是面向未来的实现。
注意事项
现在需要指出一个问题,之前我们都是将指定环境的参数写在了config-client项目的bootstrap.properties
启动文件中:这是不合理的操作,正确的做法是在发布脚本的启动命令中使用1
2
3
4
5
6
7
8
9
10
11# Nacos多环境参数配置
# 使用Data ID来实现
spring.profiles.active=TEST
# Nacos多环境参数配置
# 使用GROUP来实现
spring.cloud.nacos.config.group=PROD_GROUP
# Nacos多环境参数配置
# 使用Namespace来实现
spring.cloud.nacos.config.namespace=dde555e6-2539-4d50-be82-1384222324d2-D
参数并配置上述选项参数来动态指定配置,这似乎是更合理的操作。
加载多个配置
前面学习的加载配置都是直接加载一个配置文件,但是在实际开发过程中经常会遇到这么一种情况:一个配置文件内的信息是由多个配置文件组合而成的,这种做法非常常见,根据配置信息的具体作用存储到不同的配置文件中,这样不仅利于识别和归类,也便于共享不同配置信息给不同的应用。
Nacos在设计之初时就考虑到了这一点,通过加载不同的配置文件来实现配置信息的集中使用。
我们知道Nacos配置内容中的三个参数与具体应用的配置对应关系如下所示:
(1)Data ID
中的config-client其实对应于客户端中spring.cloud.nacos.config.prefix
参数,其值默认为${spring.application.name}
,也就是服务名称;
(2)Data ID
中的properties其实对应于客户端中spring.cloud.nacos.config.file-extension
参数,其值默认为properties;
(3)Group其实对应于客户端中spring.cloud.nacos.config.group
参数,其值默认为DEFAULT_GROUP。
也就是说默认情况下,Data ID
的值为${spring.application.name}.properties
,而Group的值为DEFAULT_GROUP。你可能有些好奇,不是介绍Nacos加载多个配置么,怎么又回到了开头介绍的Nacos配置内容中的三个参数呢?那是因为这三个参数非常重要,接下来就通过一个实际的例子来演示Nacos如何加载多个配置。
例子:假设目前Nacos已经将所有应用的数据库配置信息和日志输出信息进行统一的配置管理,现在希望将Nacos中集中管理的配置信息进行拆分,分别将这些数据拆分到分开存放的数据库配置文件database.properties
和日志输出配置文件log.properties
中。此时开发者只需要进行如下三步操作:
第一步,在Nacos中创建多Dada ID
环境配置。按照图示在Nacos中配置多Dada ID
环境,这里配置了两个Dada ID
环境:database.properties
和log.properties
,如下所示:
其中Data ID
为database.properties
的端口号为8027,group使用的是默认的DEFAULT_GROUP,同时我们还设置了一个envythink属性,其值为multi-config。
其中Data ID
为log.properties
的端口号为8027,group使用的是默认的DEFAULT_GROUP:
第二步,指定使用环境。在config-client客户端的bootstrap.properties
启动文件中(正常是发布脚本的命令中通过指定参数来动态指定)指定要获取的环境,可以通过如下参数来实现:
1 | # Nacos配置中心配置 |
请注意这里笔者使用spring.cloud.nacos.config.extension-configs
参数来配置要加载的这上述两个配置内容。通过查看其源码可以知道,它是一个NacosConfigProperties.Config
类型的数组,然后查看这个NacosConfigProperties.Config
类型的源码:
1 | public static class Config { |
可以看到它有三个参数,dataid就是我们前面介绍的Data ID
配置集ID;group就是Group配置分组;refresh比较特殊,之前没有介绍,它用来控制这个配置文件中的内容是否支持自动刷新,默认情况下,只有默认加载的配置才会自动刷新,而对于扩展的配置内容,则必须设置该参数为true时才会自动刷新。
通过这里的配置就可以得到组名为DEFAULT_GROUP下的database.properties
和log.properties
文件中的内容:
第三步,启动项目并测试。首先确保之前下载的nacos服务已经正常运行,然后启动这里名为config-client的服务,并打开浏览器访问http://localhost:8027/hello
,可以看到结果返回multi-config:
共享配置
其实眼尖的童鞋在前面查看extensionConfigs源码的时候就发现了一个名为sharedConfigs的属性,且两者都是一个NacosConfigProperties.Config
类型的数组,里面存放的都是同一个NacosConfigProperties.Config
对象。
因此两者的使用似乎没有差别,唯一不同的则是体现在config-client客户端的bootstrap.properties
启动文件中配置参数:
1 | # Nacos配置中心配置 |
仅仅是将前面的extension-configs换成了shared-configs,就实现了从加载多配置到共享配置的实现,也就是说其实这里的加载多配置和共享配置其实是相同的功能。
配置加载的优先级
前面三种方式都能加载多个配置,那么这样就存在一个问题,当我们同时使用三种配置方式来加载多个配置时,这三者加载的优先级是怎样的。这三种配置方式如下所示:
(1)通过使用前面多次提到的三个参数spring.cloud.nacos.config.prefix
、spring.cloud.nacos.config.file-extension
和spring.cloud.nacos.config.group
拼接出来的地址去加载配置文件;
(2)通过使用spring.cloud.nacos.config.extension-configs[n]
的data-id
、group
和refresh
参数定义的加载多配置文件;
(3)通过使用spring.cloud.nacos.config.shared-configs[n]
的data-id
、group
和refresh
参数定义的共享多配置文件。
我们可以基于上述例子来进行验证,在config-client客户端的bootstrap.properties
启动文件中分别使用三种配置加载方式来指定各自要获取的环境,可以通过如下参数来实现:
1 | # 加载配置优先级 |
然后启动项目并查看config-client项目控制台的输出情况,如下所示:
由于后面加载的配置会覆盖之前加载的配置,因此我们就可以得出三者的优先级为:拼接配置 > 加载多配置extension-configs
> 共享配置shared-configs
。
这样关于Nacos实现配置中心的学习差不多就结束了,虽然对于Nacos系统参数这一部分还没结束,但是开发者完全可以自行点击 这里来进行有选择行的学习。
参考文章:**Nacos配置的多环境管理**、 Nacos官方文档