3 Nacos配置管理

3.1 理解配置中心

3.1.1 什么是配置

应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数 据库连接参数、启动参数等。

配置主要有以下几个特点:

配置是独立于程序的只读变量

配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置 配置伴随应用的整个生命周期

配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。 比如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。

配置可以有多种加载方式

常见的有程序内部hard code,配置文件,环境变量,启动参数,基于数据库等,配置需要治理

同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的 配置,所以需要有完善的环境、集群配置管理

3.1.2 什么是配置中心

在微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移

(分割),这样配置就分散了,不仅如此,分散中还包含着冗余,如下图:

下图显示了配置中心的功能,配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去 管理配置。

配置中心的服务流程如下:

1、用户在配置中心更新配置信息。

2、服务A和服务B及时得到配置更新通知,从配置中心获取配置。

总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。

在系统架构中,配置中心是整个微服务基础架构体系中的一个组件,如下图,它的功能看上去并不起眼,无非就是 配置的管理和存取,但它是整个微服务架构中不可或缺的一环。

总结一下,在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系 统组件,在这种背景下中心化的配置服务即配置中心应运而生,一个合格的配置中心需要满足如下特性:

配置项容易读取和修改

分布式环境下应用配置的可管理性,即提供远程管理配置的能力 支持对配置的修改的检视以把控风险

可以查看配置修改的历史记录

不同部署环境下应用配置的隔离性

3.1.3 主流配置中心对比

目前市面上用的比较多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等。由于Disconf不再维护,下面主要对比一下Spring Cloud Config、Apollo和Nacos。

对比项目

Spring Cloud Config

Apollo

Nacos

配置实时推送

支持(Spring Cloud Bus)

支持(HTTP长轮询1s内)

支持(HTTP长轮询1s内)

版本管理

支持(Git)

支持

支持

配置回滚

支持(Git)

支持

支持

灰度发布

支持

支持

不支持

权限管理

支持(依赖Git)

支持

不支持

多集群

支持

支持

支持

多环境

支持

支持

支持

监听查询

支持

支持

支持

多语言

只支持Java

主流语言,提供了Open API

主流语言,提供了Open API

配置格式校验

不支持

支持

支持

单机读(QPS)

7(限流所致)

9000

15000

单击写(QPS)

5(限流所致)

1100

1800

3节点读(QPS)

21(限流所致)

27000

45000

3节点写(QPS)

5(限流所致)

3300

5600

从配置中心角度来看,性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Config依赖Git场景不适合开放的大规模自动化运维API。功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud

Config不带运维管理界面,需要自行开发。Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比

Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。

综合来看,Nacos的特点和优势还是比较明显的,下面我们一起进入Nacos的世界。

3.2 Nacos配置管理

3.2.1 发布配置

首先在nacos发布配置,nacos-restful-consumer服务从nacos读取配置。

浏览器访问 http://127.0.0.1:8848/nacos ,打开nacos控制台,并点击菜单配置管理**->配置列表**: 在Nacos添加如下的配置:

nacos-restful-consumer:

Namespace: public
DataID:  nacos-restful-consumer.yaml
Group:  DEFAULT_GROUP
配置格式:      YAML
配置内容:    
common:
  name: application1 config

3.2.2 获取配置

要想从配置中心获取配置 添加nacos-config的依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

在bootstrap.yml添加配置:

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址
        file-extension: yaml
        group: DEFAULT_GROUP

注意:要使用配置中心就要在bootstrap.yml中来配置,bootstrap.yml配置文件的加载顺序要比application.yml要优先。

在nacos-restful-consumer工程的controller中增加获取配置的web访问端点/configs,

通过标准的spring @Value方式。

@Value("${common.name}") 
private String common_name;

@GetMapping(value = "/configs")
public String getvalue(){
    return common_name;
}

基于上面的例子,若要实现配置的动态更新,只需要进行如下改造:

// 注入配置文件上下文
@Autowired
private ConfigurableApplicationContext applicationContext;

@GetMapping(value = "/configs")
public String getConfigs(){
    return applicationContext.
        getEnvironment().getProperty("common.name");
}

我们通过nacos控制台更新common.name的配置值,再次访问web端点/configs,发现应用程序能够获取到最新的配置值,

说明spring-cloud-starter-alibaba-nacos-config 支持配置的动态更新。

Note:可以通过配置 spring.cloud.nacos.config.refresh.enabled=false 来关闭动态刷新

3.2.3 配置管理模型

对于Nacos配置管理,通过Namespace、group、Data ID能够定位到一个配置集。

配置集(Data ID)

在系统中,一个配置文件通常就是一个配置集,一个配置集可以包含了系统的各种配置信息,例如,一个配置集可 能包含了数据源、线程池、日志级别等配置项。每个配置集都可以定义一个有意义的名称,就是配置集的ID 即DataID。

配置项

配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形式存在。例如我们常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

配置分组(Group)

配置分组是对配置集进行分组,通过一个有意义的字符串(如 Buy 或 Trade )来表示,不同的配置分组下可以有相同的配置集(Data ID)。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:可用于区分不同的项目或应用,例如:学生管理系统的配置集可以定义一个group为:STUDENT_GROUP。

命名空间(Namespace)

命名空间(namespace)可用于进行不同环境的配置隔离。例如可以隔离开发环境、测试环境和生产环境,因为 它们的配置可能各不相同,或者是隔离不同的用户,不同的开发人员使用同一个nacos管理各自的配置,可通过namespace隔离。不同的命名空间下,可以存在相同名称的配置分组(Group) 或 配置集。

最佳实践

Nacos抽象定义了Namespace、Group、Data ID的概念,具体这几个概念代表什么,取决于我们把它们看成什么,这里推荐给大家一种用法,如下图:

Namespace:代表不同环境,如开发、测试、生产环境。

Group:代表某项目,如XX医疗项目、XX电商项目

DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件

获取某配置集的代码: 获取配置集需要指定:

1、nacos服务地址,必须指定

2、namespace,如不指定默认public

在config中指定namespace,例子如下:

config:
  server-addr: 127.0.0.1:8848 # 配置中心地址
  file-extension: yaml
  namespace: 4883fa0a-8f2b-4b3d-b8f5-261dfe06a323 # 开发环境
  group: DEFAULT_GROUP # xx业务组

3、group,如不指定默认 DEFAULT_GROUP

见上边第2点的例子。

4、dataId,必须指定,名称为应用名称+配置文件扩展名

3.3 自定义扩展的 Data Id 配置

3.3.1 ext-config扩展配置

Spring Cloud Alibaba Nacos Config可支持自定义 Data Id 的配置。 一个完整的配置案例如下所示:

server:
  port: 56020
nacos:
  server:
    addr: 127.0.0.1:8848
provider:
  address: 127.0.0.1:56010
spring:
  application:
    name: nacos_consumer
  cloud:
    nacos:
      discovery:
        server-addr: ${nacos.server.addr}
      config:
        server-addr: ${nacos.server.addr} # 配置中心地址
        file-extension: yaml
        ext-config[0]:
          data-id: ext-common.yaml
          group: COMMON_GROUP
          refresh: true

可以看到:

通过 spring.cloud.nacos.config.ext-config[n].data-id 的配置方式来支持多个 Data Id 的配置。

通过 spring.cloud.nacos.config.ext-config[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是DEFAULT_GROUP。

通过spring.cloud.nacos.config.ext-config[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。

spring.cloud.nacos.config.ext -config[n].data-id 的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file -extension 的配置对自定义扩 展配置的 Data Id 文件扩展名没有影响。

测试:

配置ext-config-common01.yaml:

配置ext-config-common02.yaml:

编写测试代码:

@GetMapping(value = "/configs") 
public String getvalue(){
    String name = applicationContext.
        getEnvironment().getProperty("common.name");
    String address =  applicationContext.
        getEnvironment().getProperty("common.addr");
    return name + address;
}

重启nacos-restful-consumer工程

访问 :http://127.0.0.1:56020/configs 通过测试发现:

扩展配置优先级是 spring.cloud.nacos.config.ext -config[n].data-id 其中 n 的值越大,优先级越高。 通过内部相关规则(应用名、扩展名 )自动生成相关的 Data Id 配置的优先级最大。

3.3.2 案例

案例需求如下:

1、抽取servlet公用的配置到独立的配置文件,配置文件内容如下:

#tomcat头信息和访问路径配置
server:
  tomcat:
    remote_ip_header: x‐forwarded‐for
    protocol_header: x‐forwarded‐proto
  servlet:
    context‐path: /a
    use‐forward‐headers: true

2、如果有context-path的个性配置可以单独设置实现如下:

1、抽取servlet公用的配置到独立的配置文件

在nacos-restful-consumer中添加扩展配置文件,下图中红色框内为指定的配置文件名称:

在nacos中添加扩展配置文件,下图中红色框内是servlet公用的配置内容。

发布配置,重启nacos-restful-consumer

访问 http://127.0.0.1:56020/a/configs 验证配置是否生效

2、如果有context-path的个性配置可以单独设置

这里我们需要对nacos-restful-consumer的context-path设置为根路径,如何实现?

方案1:修改ext-config-http.yaml中context-path为根路径,但是此文件定义为公用配置文件,其它服务也使用了,此方案不可行。

方案2:在nacos-restful-consumer.yaml中定义context-path为根路径,因为nacos-restful-consumer.yaml单独属于nacos-restful-consumer工程,且nacos-restful-consumer.yaml的优先级比ext-config-http.yaml高,所以此方案可行。

在nacos中配置nacos-restful-consumer.yaml,如下:

重启nacos-restful-consumer工程。

测试,请求:http://127.0.0.1:56020/configs