图文详述Nacos配置中心使用:应用间配置共享、扩展配置文件加载优先级、新老版本差异

简介: 图文详述Nacos配置中心使用:应用间配置共享、扩展配置文件加载优先级、新老版本差异

一、前言

项目上使用Nacos做为配置中心,以前使用的是Concul;现在准备详细梳理一下Nacos做为配置中心的配置文件加载优先级问题,因为以前在使用Consul的时候,由于配置文件优先级问题踩过大坑。

二、实战

1、集成Nacos配置中心

1) POM中引入SpringCloud、Spring Cloud Alibaba依赖,记得做好maven版本管理、否则存在版本问题一地鸡毛的场景。

<properties>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>

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

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--整合spring cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR8</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--整合spring cloud alibaba-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

2) 在bootstrap.yml中配置Nacos-server的地址

server:
  port: 9001

spring:
  application:
    name: config1 # 配置名,即Nacos dashboard中的Data id
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址,集群的话多个节点使用,分隔
        file-extension: yaml # 配置的后缀名
        namespace: 2c38da96-f654-4105-bbc0-63befaa449f0 # 命名空间ID
        group: DEFAULT_GROUP # 指定要获取配置的组

在这里插入图片描述
3) 随便写个Controller,用@Value等注解或ConfigurableApplicationContext获取配置信息。

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhouxin
 * @RefreshScope 动态加载配置
 **/
@RefreshScope
@RestController
public class NacosServerController {

    @Resource
    private ConfigurableApplicationContext configurableApplicationContext;

    /**
     * 可用于验证本服务配置文件和extension-configs之间的优先级
     */
    @Value("${student.name:null}")
    private String name;

    /**
     * 如果只是通过@Value获得的配置信息,不会随着Nacos的修改操作而获得最新配置信息。那么,实时获取最新配置信息有两种方式:
     * 方式1:添加@RefreshScope注解。
     * 方式2:通过getProperty的方式,获得最新的配置信息。
     *
     * @return
     */
    @GetMapping("/name")
    public String getName() {
        String name1 = configurableApplicationContext.getEnvironment().getProperty("student.name");
        return String.format("name=%s <br> name1=%s", name, name1);
    }

Nacos服务端config1.yaml配置如下:
在这里插入图片描述
启动服务,通过HTTP访问(http://localhost:9001/name)到的结果如下:
在这里插入图片描述
这说明:我们可以通过很多中方式注入配置,包括:@Value、@ConfigurationProperties、ConfigurableApplicationContext等。

2、应用配置共享

Nacos提供两种应用间共享配置的方式:扩展DataId(extension-configs)、共享DataId(shared-configs);另外需共享的DataId,yaml后缀不能少,且目前只支持yaml/properties。

0)Nacos服务端配置准备

(1)config1.yaml

在这里插入图片描述

(2)config2.yaml

在这里插入图片描述

(3)config3.yaml在这里插入图片描述

(4)config4.yaml

在这里插入图片描述

(5)config5.yaml

在这里插入图片描述

1)扩展Data Id配置

Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义扩展Data Id 配置,特性如下:

1、支持多个 Data Id 的配置;

通过 spring.cloud.nacos.config.extension-configs[n].data-id 的配置方式

2、可以自定义Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP;

通过 spring.cloud.nacos.config.extension-configs[n].group 的配置方式

3、当某个Data Id 的配置变更时,自定义应用中是否动态刷新配置值,默认为否;

通过 spring.cloud.nacos.config.extension-configs[n].refresh 的配置方式

源码中的体现:

(1)在bootstrap.yml文件中按住command 鼠标左键点extension-configs,进入如下源码:
在这里插入图片描述
从上面我们可以看出扩展DataID的主体是Config类,我们看一下它:
在这里插入图片描述
从这里我们便能看出上面提到的extension-configs的特性和一些默认值。

使用:

(1)bootstrap.yml文件中增加如下配置:

spring:
  cloud:
    nacos:
      config:
        # 使用extension-configs[n],配置加载多个dataId
        extension-configs:
          - data-id: config4.yaml
            group: CONFIG4_GROUP
            refresh: true  # 动态刷新配置
          - data-id: config5.yaml
            group: DEFAULT_GROUP
            refresh: true  # 动态刷新配置

(2)controller中引入只存在于config4.yaml和config5.yaml中的配置:

@Value("${config4.name:null}")
private String config4Name;

@Value("${config5.name:null}")
private String config5Name;

@GetMapping("/allname")
public String getAllName() {
    return String.format("config4Name=%s <br> config5Name=%s", config4Name, config5Name);
}

通过HTTP访问(http://localhost:9001/allname)到的结果如下:
在这里插入图片描述

2)共享Data Id配置

为了更加清晰的在多个应用间配置共享的 Data Id ,也可以通过以下的方式来配置:

1、支持多个 Data Id 的配置;

通过 spring.cloud.nacos.config.shared-configs[n].data-id 的配置方式

2、可以自定义Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP;

通过 spring.cloud.nacos.config.shared-configs[n].group 的配置方式

3、当某个Data Id 的配置变更时,自定义应用中是否动态刷新配置值,默认为否;

通过 spring.cloud.nacos.config.shared-configs[n].refresh 的配置方式

使用:

(1)bootstrap.yml文件中增加如下配置:

spring:
  cloud:
    nacos:
      config:
        # 使用shared-config[n],配置加载多个dataId
        shared-configs:
          - data-id: config2.yaml
            group: DEFAULT_GROUP
            refresh: true  # 动态刷新配置
          - data-id: config3.yaml
            group: DEFAULT_GROUP
            refresh: true  # 动态刷新配置

(2)controller中引入只存在于config2.yaml和config3.yaml中的配置:

@Value("${config2.name:null}")
private String config2Name;

@Value("${config3.name:null}")
private String config3Name;

@GetMapping("/allname")
public String getAllName() {
    return String.format("config2Name=%s <br> config3Name=%s", config2Name, config3Name);
}

通过HTTP访问(http://localhost:9001/allname)到的结果如下:
在这里插入图片描述

聪明的大家肯定发现这和extension-configs扩展DataId的方式一毛一样啊,是的,它就一毛一样。
但是注意,在老版本中它俩的扩展方式还真不一样,下面我们来看一下新老版本扩展/共享DataId的差异?

3、扩展/共享DataId新老版本差异

1)老版本的pom

<properties>
    <java.version>1.8</java.version>
    <spring.boot>2.1.3.RELEASE</spring.boot>
    <spring.cloud>Greenwich.RELEASE</spring.cloud>
    <spring.cloud.alibaba>2.1.0.RELEASE</spring.cloud.alibaba>
</properties>

<dependencyManagement>
<dependencies>
    <!-- 引入Spring Cloud Alibaba依赖 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>${spring.cloud.alibaba}</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <!-- 引入Spring Cloud依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring.cloud}</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <!-- 引入Spring Boot依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${spring.boot}</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencies>
</dependencyManagement>

2)扩展DataId方式的差异

新版本yaml中使用extension-configs,老版本yaml使用ext-config;除此之外,功能上并没有区别。
在这里插入图片描述

3)分享DataId方式的差异

(1)使用上:

1、新版本yaml中使用 shared-configs
2、老版本yaml使用 shared-dataids根据DataID加载配置信息、使用 refreshable-dataids实现指定DataId配置信息的动态刷新;

2)功能上:

新版本yaml中支持指定group,老版本中不支持指定Group,只会取默认的group-- DEFAULT_GROUP

在这里插入图片描述
为什么老版本不支持指定group呢?我们来看一下:

3)源码分析

(1) 在bootstrap.yml文件中按住command 鼠标左键点shared-dataids,进入如下源码:
在这里插入图片描述

public static final String SEPARATOR = "[,]";

这里我们可以看到它会将传入的sharedDataids以,分隔为多个DataId,并将DataId作为入参构造Config:
在这里插入图片描述
其中只会指定dataId,并不会牵扯到group。

(2) 我们再看shared-dataids
在这里插入图片描述
在这里插入图片描述
它也只是将拆分出的所有dataId对应的Config的refresh属性设置为true,也不牵扯到group。

(3)会不会有group-dataids呢?
进入NacosConfigProperties类中全局搜索一把,并没有。

好了,新老版本的差异我们也聊完了,下面看一下配置文件加载的优先级吧。

4、扩展的配置文件加载优先级

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

(1)以老版本来说:

1、shared-dataids中越靠后,优先级越高;
2、ext-config中n越大、或越靠后,优先级越高;
3、Shared-dataids < ext-config < 内部;

(2)以新版本来说:

1、shared-configs中n越大、或越靠后,优先级越高;
2、extension-configs中n越大、或越靠后,优先级越高;
3、shared-configs < extension-configs < 内部;

1)逻辑图

在这里插入图片描述
相信大家看了这个图,也不需要做过多解释了。

2)代码

(1)controller:

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhouxin
 * @RefreshScope 动态加载配置
 **/
@RefreshScope
@RestController
public class NacosServerController {

    @Resource
    private ConfigurableApplicationContext configurableApplicationContext;

    /**
     * 可用于验证本服务配置文件和extension-configs之间的优先级
     */
    @Value("${student.name:null}")
    private String name;

    @Value("${config2.name:null}")
    private String config2Name;

    @Value("${config3.name:null}")
    private String config3Name;

    @Value("${config4.name:null}")
    private String config4Name;

    @Value("${config5.name:null}")
    private String config5Name;

    /**
     * 用于验证shared-configs之间的优先级
     */
    @Value("${config.name:null}")
    private String configName;

    /**
     * extension-configs和shared-configs的优先级
     */
    @Value("${ext.name:null}")
    private String extName;

    /**
     * 用于验证extension-configs之间的优先级
     */
    @Value("${ext.gender:null}")
    private String extGender;

    /**
     * 如果只是通过@Value获得的配置信息,不会随着Nacos的修改操作而获得最新配置信息。那么,实时获取最新配置信息有两种方式:
     * 方式1:添加@RefreshScope注解。
     * 方式2:通过getProperty的方式,获得最新的配置信息。
     *
     * @return
     */
    @GetMapping("/name")
    public String getName() {
        String name1 = configurableApplicationContext.getEnvironment().getProperty("student.name");
        return String.format("name=%s <br> name1=%s", name, name1);
    }

    @GetMapping("/allname")
    public String getAllName() {
        return String.format("config1Name=%s<br> config2Name=%s<br> config3Name=%s<br> config4Name=%s <br> config5Name=%s <br> configName=%s <br> extName=%s <br> extGender=%s", name,
                config2Name, config3Name, config4Name, config5Name, configName, extName, extGender);
    }
}

(2)新版本bootstrap.yml配置:

server:
  port: 9001

spring:
  application:
    name: config1
  cloud:
    nacos:
      config:
        # 此处的nacos用于配置管理
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: 2c38da96-f654-4105-bbc0-63befaa449f0 # 命名空间ID
        group: DEFAULT_GROUP # 指定要获取配置的组
        shared-configs:
          - data-id: config2.yaml
            refresh: true
          - data-id: config3.yaml
            refresh: true
        extension-configs:
          - data-id: config4.yaml
            group: CONFIG4_GROUP
            refresh: true  # 动态刷新配置
          - data-id: config5.yaml
            group: DEFAULT_GROUP
            refresh: true  # 动态刷新配置

(3)老版本bootstrap.yml配置:

server:
  port: 9001

spring:
  application:
    name: config1 # 配置名
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址——单机
        file-extension: yaml # 后缀名
        namespace: 2c38da96-f654-4105-bbc0-63befaa449f0 # 命名空间ID
        group: DEFAULT_GROUP # 指定要获取配置的组

        # 使用shared-dataids,配置加载多个dataId
        shared-dataids: config2.yaml,config3.yaml
        refreshable-dataids: config2.yaml

        # 使用ext-config[n],配置加载多个dataId
        ext-config:
          - data-id: config4.yaml
            group: CONFIG4_GROUP
            refresh: true  # 动态刷新配置
          - data-id: config5.yaml
            group: DEFAULT_GROUP
            refresh: true  # 动态刷新配置

在这里插入图片描述

5、本地和远程配置优先级

SpringCloud中,nacos是借助SpringCloud的Config来加载属性源的,所以是否覆盖系统属性和配置文件属性的设置也是通过SpringCloud的配置进行触发。

默认情况下nacos属性源配置优先级最高,会覆盖系统属性源和配置属性源(本地文件)

可以通过在远程配置中心(Nacos服务中)中做如下配置,设置本地配置覆盖远程配置:

spring:  
  cloud:
    config:
      # Nacos远程配置是否不覆盖其他属性源(文件、系统),默认为false,即覆盖其他源(文件、系统),当allow-override:为true时才会生效
      override-none: true
      # 是否允许Nacos远程配置被本地文件覆盖,默认为true
      allow-override: true
      # Nacos远程配置是否可以覆盖系统属性源(系统环境变量或系统属性),默认为true,即允许
      override-system-properties: false

在这里插入图片描述

注意:

1、将其放在bootstrap.yml或application.yml配置文件中是无效的。
2、如果allow-override值为false,即使将override-none设置为true,也是无效的。

6、其他

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

更多Nacos-config的内容请参考Nacos的GitHub Wiki:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config

三、最佳实践

仁者见仁智者见智,仅供参考;

1、能放本地、不放远程;避免滥用远程服务器;
2、尽量规避优先级;
3、定规则,例如所有配置属性都要加上注释;
4、配置管理人员尽量少;

最后,虽然我用的Nacos1.4.1版本,但是不建议大家在生产环境使用这个版本,因为该版本存在一个致命的bug:

客户端与 Nacos Server 如果发生短暂的域名解析问题,会导致心跳永久丢失,进而引发服务全量下线,即使网络恢复,也不会自动恢复心跳。

域名解析失败常见于网络抖动或者 K8s 环境下的 coreDNS 访问超时等场景,并且该问题仅存在于 1.4.1 版本,低于此版本不受此问题的影响,使用 1.4.1 的用户建议升级至 1.4.2 以避免此问题(源自阿里内部博文)。

相关文章
|
1天前
|
JSON Java Nacos
SpringCloud 应用 Nacos 配置中心注解
在 Spring Cloud 应用中可以非常低成本地集成 Nacos 实现配置动态刷新,在应用程序代码中通过 Spring 官方的注解 @Value 和 @ConfigurationProperties,引用 Spring enviroment 上下文中的属性值,这种用法的最大优点是无代码层面侵入性,但也存在诸多限制,为了解决问题,提升应用接入 Nacos 配置中心的易用性,Spring Cloud Alibaba 发布一套全新的 Nacos 配置中心的注解。
|
16天前
|
Java 网络安全 Nacos
Nacos作为流行的微服务注册与配置中心,其稳定性与易用性广受好评
Nacos作为流行的微服务注册与配置中心,其稳定性与易用性广受好评。然而,“客户端不发送心跳检测”是使用中常见的问题之一。本文详细探讨了该问题的原因及解决方法,包括检查客户端配置、网络连接、日志、版本兼容性、心跳检测策略、服务实例注册状态、重启应用及环境变量等步骤,旨在帮助开发者快速定位并解决问题,确保服务正常运行。
40 5
|
28天前
|
监控 Java 测试技术
Nacos 配置中心变更利器:自定义标签灰度
本文是对 MSE Nacos 应用自定义标签灰度的功能介绍,欢迎大家升级版本进行试用。
114 10
|
1月前
|
网络安全 Nacos 开发者
Nacos作为流行的微服务注册与配置中心,“节点提示暂时不可用”是常见的问题之一
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,“节点提示暂时不可用”是常见的问题之一。本文将探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务的正常运行。通过检查服务实例状态、网络连接、Nacos配置、调整健康检查策略等步骤,可以有效解决这一问题。
35 4
|
5月前
|
Java Nacos 数据库
使用 nacos 搭建注册中心及配置中心
使用 nacos 搭建注册中心及配置中心
104 5
|
5月前
|
NoSQL Java Nacos
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
SpringCloud集成Seata并使用Nacos做注册中心与配置中心
166 3
|
1月前
|
负载均衡 应用服务中间件 Nacos
Nacos配置中心
Nacos配置中心
65 1
Nacos配置中心
|
1月前
|
Java 网络安全 Nacos
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。
Nacos作为流行的微服务注册与配置中心,其稳定性和易用性备受青睐。然而,实际使用中常遇到“客户端不发送心跳检测”的问题。本文深入探讨该问题的原因及解决方案,帮助开发者快速定位并解决问题,确保服务正常运行。通过检查客户端配置、网络连接、日志、版本兼容性、心跳策略、注册状态、重启应用和环境变量等步骤,系统地排查和解决这一问题。
48 3
|
1月前
|
安全 Nacos 数据库
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改
Nacos是一款流行的微服务注册与配置中心,但直接暴露在公网中可能导致非法访问和数据库篡改。本文详细探讨了这一问题的原因及解决方案,包括限制公网访问、使用HTTPS、强化数据库安全、启用访问控制、监控和审计等步骤,帮助开发者确保服务的安全运行。
42 3
|
1月前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
61 0