Alibaba微服务组件 - Nacos配置中心

1. 什么是Nacos配置中心

官方文档: https://github.com/alibaba/spring­cloud­alibaba/wiki/Nacos­config
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。
主要解决的问题:

  • 维护性
  • 时效性
  • 安全性
    image

对比springcloud config 对比
三大优势:

  • springcloud config大部分场景结合git 使用, 动态变更还需要依赖Spring Cloud Bus 消息总线来通过所有的客户端变化.
  • springcloud config不提供可视化界面
  • nacos config使用长轮询更新配置, 一旦配置有变动后,通知Provider的过程非常的迅速, 从速度上秒杀springcloud原来的config几条街,

image

2. 快速开始

准备配置,nacos server中新建com.xiexie.maill.order
image
image

最佳实践:
Namespace:代表不同环境,如开发、测试、生产环境。
Group:代表某项目,如XX医疗项目、XX电商项目
DataId:每个项目下往往有若干个工程(微服务),每个配置集(DataId)是一个工程(微服务)的主配置文件
image

3. 权限配置

如果需要对安全性做处理,需要开启权限
启动权限:修改application.properties
image

4. 搭建nacos-config服务

通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更

4.1 引入依赖

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

4.2 添加bootstrap.properties(或者添加bootstrap.yml)

bootstrap.yml文件

spring:
  application:
    # 会自动根据服务名去拉取nacos中Data Id对应的配置文件,如果dataid跟服务名不一致,就需要手动指定dataid
    # 跟服务名相同的dataid配置文件,就叫做默认的配置文件
    # 除了默认的配置文件properties扩展名,其他的所有dataid都需要加上后缀扩展名
    name: com.xiexie.maill.order
  cloud:
    nacos:
      server-addr: 192.168.5.133:8848
      # 当nacos开启权限配置的时候 需要加我们的用户名和密码
      username: nacos
      password: nacos
      # 绑定我们的命名空间(如果是public则不需要写,防止频繁出现ClientWorker日志)
      config:
        namespace: 6325e312-7f95-48d7-8d06-810047ed3956
        group: group-test
        # 基于 dataid 为 yaml 的文件扩展名配置方式
        # nacos客户端拉取的配置文件扩展名默认为properties,
        # 一旦修改成非properties文件格式,必须通过file-extension进行设置指定
        # 只针对默认的配置文件和profile,其他自定义dataid进行扩展可以随意
        file-extension: yaml
        # 客户端关闭动态刷新配置文件
        # refresh-enabled: false

        # shared-configs 自定义dataid扩展
        shared-configs:
          - dataId: com.xiexie.shared.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true
          # 数组list下标越大优先级越大(list后面的优先级大)
          - dataId: com.xiexie.extension02.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true

        # extension-configs 自定义dataid扩展
        extension-configs:
          - dataId: com.xiexie.extension.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true
          # 数组list下标越大优先级越大(list后面的优先级大)
          - dataId: com.xiexie.extension02.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true

# 配置文件的优先级(优先级大的会覆盖优先级小的,并且会形成互补) 下面的优先级由大到小
# profile > 默认配置文件 > extension-configs(组list下标越大优先级越大(list后面的优先级大)) > shared-configs(组list下标越大优先级越大(list后面的优先级大))
# com.xiexie.maill.order-dev.ymal(精致匹配);
# com.xiexie.maill.order.ymal(同工程不同环境的通用配置);
# extension-configs 不同工程扩展配置(组list下标越大优先级越大(list后面的优先级大));
# shared-configs 不同工程通用配置(组list下标越大优先级越大(list后面的优先级大));
# ext-config(不同工程的); (废弃方法 但是可以用)
# shared-dataids 不同工程通用配置; (废弃方法 但是可以用)

如果是要指定profile的话在application.yml中设置,也可以在bootstrap.yml文件中设置,这样更好区分
application.yml

server:
  port: 8050

# 配置profile指定配置文件
spring:
  profiles:
    active: dev

# 在配置中心可以使用profile进行设置
# 只有默认的配置文件才能结合使用profile进行使用
# 对应的dataid: ${spring.application.name}-${profile}.${file-extension:properties}
# profile的后缀必须跟随默认配置文件的格式来

4.3 启动服务,测试微服务是否使用配置中心的配置

package com.xiexie.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Date 2022-04-12 9:11
 * @Author xie
 */
@SpringBootApplication
public class ConfigApplication {

    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);

        while (true) {
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            String config = applicationContext.getEnvironment().getProperty("user.config");
            System.err.println("user name :"+userName+"; age: "+userAge + "; config: " + config);
            // 一秒钟拉取一次
            TimeUnit.SECONDS.sleep(1);
        }
        // nacos客户端每10ms 去注册中心拉取一次,是根据注册中心的MDS值去更新的(每次更改配置中会有历史版本,新版本会生成新的MD5值)
        // 当发现客户端缓存的MD5值不一样时,就会卡去更新的配置文件信息
        /**
         * 当一直出现c.a.n.client.config.impl.ClientWorker    : [fixed-192.168.5.133_8848-public] [polling-resp] config changed
         * 这个信息时候,有两个原因
         * 1. 绑定我们的命名空间为public时候,不需要指定默认就是,注释掉;或者指定其他的命名空间
         * 2. 我们依赖的nacos客户端版本跟服务端的版本不一致(一般情况都是对应的,有问题根据具体情况查验)
         */

    }
}

image

5. Config相关配置

Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是DEFAULT_GROUP
image

5.1 支持配置的动态更新

public static void main(String[] args) throws InterruptedException {
    ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);

    while (true) {
        String userName = applicationContext.getEnvironment().getProperty("user.name");
        String userAge = applicationContext.getEnvironment().getProperty("user.age");
        String config = applicationContext.getEnvironment().getProperty("user.config");
        System.err.println("user name :"+userName+"; age: "+userAge + "; config: " + config);
        // 一秒钟拉取一次
        TimeUnit.SECONDS.sleep(1);
    }
    // nacos客户端每10ms 去注册中心拉取一次,是根据注册中心的MDS值去更新的(每次更改配置中会有历史版本,新版本会生成新的MD5值)
    // 当发现客户端缓存的MD5值不一样时,就会卡去更新的配置文件信息
    /**
     * 当一直出现c.a.n.client.config.impl.ClientWorker    : [fixed-192.168.5.133_8848-public] [polling-resp] config changed
     * 这个信息时候,有两个原因
     * 1. 绑定我们的命名空间为public时候,不需要指定默认就是,注释掉;或者指定其他的命名空间
     * 2. 我们依赖的nacos客户端版本跟服务端的版本不一致(一般情况都是对应的,有问题根据具体情况查验)
    */

}

5.2 可支持profile粒度的配置

spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,还加载了dataid为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 ${spring.profiles.active} 这个配置项来配置。

spring.profiles.active=develop

如果需要切换到生产环境,只需要更改 ${spring.profiles.active} 参数配置即可。

spring.profiles.active=product

此案例中我们通过 spring.profiles.active=<profilename> 的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=<profile> 参数指定其配置来达到环境间灵活的切换。

5.3 支持自定义 namespace 的配置

用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。如果需要使用自定义的命名空间,可以通过以下配置来实现:

spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7

该配置必须放在 bootstrap.properties 文件中。此外 spring.cloud.nacos.config.namespace 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespae,否则将会导致读取不到正确的配置。

5.4 支持自定义 Group 的配置

在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下, 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:

spring.cloud.nacos.config.group=DEVELOP_GROUP

该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 spring.cloud.nacos.config.group 的配置值一致。

5.5 支持自定义扩展的 Data Id 配置

Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 这里。 一个完整的配置案例如下所示:

spring.application.name=opensource-service-provider
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

# config external configuration
# 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新
spring.cloud.nacos.config.extension-configs[0].data-id=ext-config-common01.properties

# 2、Data Id 不在默认的组,不支持动态刷新
spring.cloud.nacos.config.extension-configs[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.extension-configs[1].group=GLOBALE_GROUP

# 3、Data Id 既不在默认的组,也支持动态刷新
spring.cloud.nacos.config.extension-configs[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.extension-configs[2].group=REFRESH_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true

可以看到:

  • 通过 spring.cloud.nacos.config.extension-configs[n].data-id 的配置方式来支持多个 Data Id 的配置。
  • 通过 spring.cloud.nacos.config.extension-configs[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
  • 通过 spring.cloud.nacos.config.extension-configs[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。
    多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.extension-configs[n].data-id 其中 n 的值越大,优先级越高

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

参考配置文件bootstrap.yml

spring:
  application:
    # 会自动根据服务名去拉取nacos中Data Id对应的配置文件,如果dataid跟服务名不一致,就需要手动指定dataid
    # 跟服务名相同的dataid配置文件,就叫做默认的配置文件
    # 除了默认的配置文件properties扩展名,其他的所有dataid都需要加上后缀扩展名
    name: com.xiexie.maill.order
  cloud:
    nacos:
      server-addr: 192.168.5.133:8848
      # 当nacos开启权限配置的时候 需要加我们的用户名和密码
      username: nacos
      password: nacos
      # 绑定我们的命名空间(如果是public则不需要写,防止频繁出现ClientWorker日志)
      config:
        namespace: 6325e312-7f95-48d7-8d06-810047ed3956
        group: group-test
        # 基于 dataid 为 yaml 的文件扩展名配置方式
        # nacos客户端拉取的配置文件扩展名默认为properties,
        # 一旦修改成非properties文件格式,必须通过file-extension进行设置指定
        # 只针对默认的配置文件和profile,其他自定义dataid进行扩展可以随意
        file-extension: yaml
        # 客户端关闭动态刷新配置文件
        # refresh-enabled: false

        # shared-configs 自定义dataid扩展
        shared-configs:
          - dataId: com.xiexie.shared.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true
          # 数组list下标越大优先级越大(list后面的优先级大)
          - dataId: com.xiexie.extension02.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true

        # extension-configs 自定义dataid扩展
        extension-configs:
          - dataId: com.xiexie.extension.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true
          # 数组list下标越大优先级越大(list后面的优先级大)
          - dataId: com.xiexie.extension02.properties
            group: DEFAULT_GROUP # 默认值可以不写
            refresh: true

# 配置文件的优先级(优先级大的会覆盖优先级小的,并且会形成互补) 下面的优先级由大到小
# profile > 默认配置文件 > extension-configs(组list下标越大优先级越大(list后面的优先级大)) > shared-configs(组list下标越大优先级越大(list后面的优先级大))
# com.xiexie.maill.order-dev.ymal(精致匹配);
# com.xiexie.maill.order.ymal(同工程不同环境的通用配置);
# extension-configs 不同工程扩展配置(组list下标越大优先级越大(list后面的优先级大));
# shared-configs 不同工程通用配置(组list下标越大优先级越大(list后面的优先级大));
# ext-config(不同工程的); (废弃方法 但是可以用)
# shared-dataids 不同工程通用配置; (废弃方法 但是可以用)

5.6 配置的优先级

Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。

  • A: 通过 spring.cloud.nacos.config.shared-configs[n].data-id 支持多个共享 Data Id 的配置
  • B: 通过 spring.cloud.nacos.config.extension-configs[n].data-id 的方式支持多个扩展 Data Id 的配置
  • C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置

当三种方式共同使用时,他们的一个优先级关系是:A < B < C

profile > 默认配置文件 > extension-configs(组list下标越大优先级越大(list后面的优先级大)) > shared-configs(组list下标越大优先级越大(list后面的优先级大))

6. @RefreshScope 实际用法

@Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,需要利用@RefreshScope注解

package com.xiexie.config.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;

/**
 * @Description
 * @Date 2022-04-12 11:26
 * @Author xie
 */
@RestController
@RequestMapping("/config")
// @Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,需要利用@RefreshScope注解
@RefreshScope
public class ConfigController {

    @Value("${user.name}")
    private String username;

    @Value("${user.config}")
    private String config;

    @RequestMapping("/test")
    public String test() {
        return "username: " + username + "; config: " + config;
    }
}

7. 完全关闭配置(扩展)

通过设置 spring.cloud.nacos.config.enabled = false 来完全关闭 Spring Cloud Nacos Config

nacos配置中心数据(配套上面代码和配置文件)

image

posted @ 2022-04-12 14:28  xiexie0812  阅读(337)  评论(0编辑  收藏  举报