Nacos 2.x 入门系列【9】配置中心

597 阅读6分钟

1. 概述

1.1 配置

在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。

在实际开发中,配置文件往往有以下一些配置:

  • 数据库地址、用户名密码
  • 各种框架的配置项,例如Spring BootMybatisRabbitMQ都有很多配置
  • 项目参数配置,例如是否开启短信登录、密码限制长度等

配置可以让静态的系统工件或者交付物(如WARJAR 包等)更好地和实际的物理运行环境进行适配。这些配置项往往都是以配置文件的形式存在,在系统部署的过程中,由系统管理员或者运维人员完成。

Spring Cloud微服务项目中,后台一般都有很多个,每个Spring Boot都有一个application.yml配置文件,这些配置是分散的,非常不方便管理。而且配置并不是一成不变的,往往还需要根据系统环境运行状态进行实时变更。

1.2 配置中心

配置中心就是一个集中式管理配置信息的解决方案,它最核心的功能就是配置管理,可以进行配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等与配置相关的活动。

常见的配置中心有:

  • Nacos
  • Apollo
  • Spring Cloud Config

在使用Nacos作为注册中心后,一般都会直接选择Nacos的配置中心,而不会去再接入一个第三方组件,接下来我们学习如何使用Nacos进行管理配置。

2. 配置模型

2.1 基础模型

Nacos 配置管理的基础模型:

  1. Nacos 提供可视化的控制台,可以对配置进行发布、更新、删除、灰度、版本管理等功能。
  2. SDK 可以提供发布配置、更新配置、监听配置等功能。
  3. SDK 通过 GRPC 长连接监听配置变更,Server 端对比 Client 端配置的 MD5 和本地 MD5是否相等,不相等推送配置变更。
  4. SDK 会保存配置的快照,当服务端出现问题的时候从本地获取。

基础模型图: 在这里插入图片描述

2.2 配置资源模型

Namespace (命名空间)的设计就是用来进行资源隔离的,我们在进行配置资源的时候可以从以下两个角度来看:

  • 单个租户
  • 多租户

从单个租户的角度来看,我们要配置多套环境的配置,可以根据不同的环境来创建 Namespace 。比如开发环境、测试环境、线上环境,我们就创建对应的 Namespacedev、test、prod),Nacos 会自动生成对应的 Namespace Id 。如果同⼀个环境内想配置相同的配置,可以通过 Group 来区分。如下图所示:

image.png

从多个租户的角度来看,每个租户都可以有自己的命名空间。我们可以为每个用户创建⼀个命名空间,并给用户分配对应的权限,比如多个租户(zhangsanlisiwangwu),每个租户都想有⼀套自己的多环境配置,也就是每个租户都想配置多套环境。那么可以给每个租户创建⼀个 Namespacezhangsan、lisi、wangwu)。同样会生成对应的 Namespace Id。然后使用 Group 来区分不同环境的配置。如下图所示:

image.png

2.3 配置存储模型(ER 图)

ER 模型图:

image.png

Nacos 存储配置有几个比较重要的表分别是:

  • config_info 存储配置信息的主表,里面包含 dataId、groupId、content、tenantId、encryptedDataKey 等数据。
  • config_info_beta 灰度测试的配置信息表,存储的内容和 config_info 基本相似。有⼀个 beta _ips 字段用于客户端请求配置时判断是否是灰度的 ip
  • config_tags_relation 配置的标签表,在发布配置的时候如果指定了标签,那么会把标签和配置的关联信息存储在该表中。
  • his_config_info 配置的历史信息表,在配置的发布、更新、删除等操作都会记录⼀条数据,可以做多版本管理和快速回滚。

3. 案例演示

:还是在之前的案例代码基础上进行集成,使用的是Spring Cloud生态环境。

3.1 环境搭建

引入配置中心依赖:

        <!--Nacos 配置中心-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

application.yml配置文件添加配置:

server:
  port: 9003
spring:
  application:
    name: order-demo
  cloud:
    nacos:
      # 服务端用户名密码
      username: nacos
      password: nacos
      # 服务发现
      discovery:
        # 命名空间
        namespace: 0faa0970-1179-4143-8aa2-cac3ee6b42ec
        # 服务端地址,默认:127.0.0.1:8848
        server-addr: 127.0.0.1:8848
      # 配置中心
      config:
        namespace: 0faa0970-1179-4143-8aa2-cac3ee6b42ec
        server-addr: 127.0.0.1:8848

这时启动项目会直接报错,提示我们没有导入配置:

09:33:07.022 [main] DEBUG org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -- Application failed to start due to an exception
org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set

3.2 自定义参数配置

配置项通常都是由参数名称与参数值组成,一组相关或者不相关的配置项的集合称为配置集,在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。

除了配置后台服务,业务系统中也会存在很多系统配置参数,比如OA系统中需要配置一个密码长度限制参数。对于这些系统配置,我们可以放在数据库进行管理,但是需要开发前端管理页面,读取配置时每次都需要查询数据库,就算使用缓存,也需要支持缓存同步。这时可以使用Nacos配置中心进行管理,这样更方便,并支持动态刷新。

对于上面的报错提示,在Nacos 1.x的版本中,使用的是bootstrap.yml添加Nacos相关配置,例如:

server:
  port: 9005
spring:
  application:
    name: app-service001
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        enabled: true

bootstrap.yml机制是由spring-cloud-starter-bootstrap提供的,Spring Boot 默认不支持,在Spring Boot 2.4之后的版本,提供了spring.config.import导入配置的方式,并支持远程配置中心,所以Spring Cloud也就移除了spring-cloud-starter-bootstrapSpring Cloud Alibaba2021.0.1.0开始,也移除了这种方式,改用spring.config.import作为默认集成配置中心的方式。

使用spring.config.import导入Nacos中的配置,nacos:system-param.yaml由两部分组成,第一部分表示某个类型的注册中心,第二部分表示对应的配置集ID

spring:
  application:
    name: order-demo
  # 导入配置
  config:
      - nacos:system-param.yaml # 在拉取nacos配置异常时会快速失败,会导致 spring 容器启动失败
      #- optional:nacos:test.yml  # 监听 DEFAULT_GROUP:test.yml
      #- optional:nacos:test01.yml?group=group_01 # 覆盖默认 group,监听 group_01:test01.yml
      #- optional:nacos:test02.yml?group=group_02&refreshEnabled=false # 不开启动态刷新
  # 省略其他......

进入到控制台,选择进行的命名空间,点击创建配置: image.png 添加配置: image.png Nacos根据以下规则找到对应的配置:

命名空间+分组+数据集ID

其中命名空间,之前我们已经介绍过了,分组表示对配置集进行分组,从而区分Data ID相同的配置集。这里未填写配置分组的名称,默认采用DEFAULT_GROUP作为分组名。当不同的应用或组件使用了相同的配置类型时,可以添加分组进行隔离。

Data ID表示配置集ID,简单理解为配置文件名称,一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。

Data ID完整格式如下:

${prefix}-${spring.profiles.active}.${file-extension}

相关说明:

  • prefix: 默认为 spring.application.name 的值,也可以通过配置项spring.cloud.nacos.config.prefix来配置。
  • spring.profiles.active: 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension: 为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

添加完成后,显示如下: image.png

使用@Value @RefreshScope注解获取配置,@RefreshScopeSpring Cloud原生注解用于实现配置自动更新:

@RequestMapping("/order")
@RestController
@RefreshScope
public class OrderController {

    @Value("${password.length}")
    Integer length;

    @GetMapping("/length")
    public Integer length() {
        return length;
    }
}

访问接口,然后修改配置,观察是否动态刷新: image.png

3.3 服务配置

除了这些自定义配置项,还可以将Spring BootMybatisRabbitMQ等各种框架的配置项放在配置中心,项目部署时,直接在Nacos中修改配置即可。

首先创建一个后台服务的配置集,Data ID为服务名加文件后缀,添加服务启动端口。除此还可以添加数据库、RedisMQ等部署时需要改动的配置项: image.png

application.yml文件中,只保存一些不会变动的配置项,以及Nacos的配置,并使用spring.config.import导入服务配置:

spring:
  application:
    name: order-demo
  cloud:
    nacos:
      # 服务端用户名密码
      username: nacos
      password: nacos
      # 服务发现
      discovery:
        # 命名空间
        namespace: 0faa0970-1179-4143-8aa2-cac3ee6b42ec
        # 服务端地址,默认:127.0.0.1:8848
        server-addr: 127.0.0.1:8848
      # 配置中心
      config:
        namespace: 0faa0970-1179-4143-8aa2-cac3ee6b42ec
        server-addr: 127.0.0.1:8848
  # 导入配置
  config:
    import:
      - nacos:order-demo.yaml  # 服务配置
      - nacos:system-param.yaml  # 系统参数配置

启动项目,查看启动端口是否使用的是配置中心的配置,无误则集成成功。

因为application.yml配置了Nacos的地址,在部署时需要修改,这时可以使用启动命令直接覆盖参数即可,例如:

java -Dspring.cloud.nacos.discovery.server-addr=xxx -Dspring.cloud.nacos.discovery.namespace=xxx -Dspring.cloud.nacos.config.server-addr=xxx ......