SpringCloud Alibaba版本教程-Nacos统一配置

在前面的教程中已经介绍了Nacos的服务注册与发现功能,而Nacos提供的另一个重要功能就是统一配置。在单机应用中,统一化配置并不是那么重要,但是在微服务环境中统一化配置就很重要了。如果现在需要改一个服务的配置,而该服务由多个相同服务的应用提供,那么我们则需要将每个服务中的配置都修改一遍,这显然在服务越多的情况下越麻烦,这也就是统一配置存在的意义了。统一配置通过集中管理配置,并提供配置刷新等功能让配置需要变更时更加方便和高效。

快速开始

还是老样子,在之前的父工程中创建新的子模块nacos-config。该模块中需要引入以下依赖:

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

如果使用的spring-cloud-alibaba版本是2021.1还需要引入以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
    <version>3.1.1</version>
</dependency>

我们的spring-cloud-alibaba版本正好是2021.1所以我们同样也需要引入该配置,最后的pom依赖如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <artifactId>spring-cloud-alibaba-demo</artifactId>
        <groupId>com.zc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>nacos-config</artifactId>
    <packaging>jar</packaging>

    <name>nacos-config</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

要使用Nacos的配置功能,首先我们需要在应用的resource目录下创建配置文件bootstrap.yml,其内容如下:

spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.11:8848,192.168.1.11:8850,192.168.1.11:8852
        username: nacos
        password: nacos
        file-extension: yaml

通常情况下我们是通过application.yml来写配置文件,而bootstrap.yml则是用来配置引导上下文的,通过这种方式我们可以将引导程序和主上下文的配置分开。

Spring Cloud应用程序通过创建引导上下文来运行,该上下文是主应用程序的父上下文。它负责从外部加载配置属性,并负责解密本地外部属性配置文件中的属性。这两个上下文共享一个环境,这也是任何Spring应用程序的外部属性的来源。引导属性(不是指引导文件中的属性)以高优先级添加,因此本地配置无法覆盖它们。

关于引导上下文这部分内容,可以参考官方文档:

https://cloud.spring.io/spring-cloud-commons/multi/multi__spring_cloud_context_application_context_services.html

接下来我们在nacos管理后台中创建配置,其中Data ID就是我们的应用名称nacos-config.yamlGroup为默认值DEFAULT_GROUP,最后配置文件格式选择YAML,其内容如下:

student:
 name: mac

最后我们通过一个接口来获取配置内容:

@RestController
public class StudentController {

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

    @GetMapping("student")
    public String student() {
        return String.format("name => [%s]", name);
    }
}

启动应用最后通过localhost:${port}/student获取的内容如下:

name => [mac]

从结果可以看出name就是我们在Nacos中配置值。

刷新配置

通过上面一个例子我们知道了统一化配置,接下来就是另一个特性刷新配置。通常我们在修改配置时需要重启应用配置才能生效,在微服务环境下显然不太可能,所以就需要动态刷新配置了。我们还是基于前面的示例代码,创建一个配置类:

@Data
@RefreshScope
@ConfigurationProperties(prefix = "student")
public class Student {
    private String name;
    private Integer age;
    private String classNo;
    private String className;
}

这个与我们平常在SpringBoot中使用的配置来说没啥太大区别,唯一的不同是增加了一个@RefreshScope,它是SpringCloud环境下提供的一个scope,通过它可以实现刷新Bean的功能。最后不要忘记增加@ConfigurationPropertiesScan或者@EnableConfigurationProperties来使刚才的配置类生效。同时在StudentController增加如下内容:

    @Resource
    private Student student;

    @GetMapping("student_refresh")
    public String studentRefresh(){
        return student.toString();
    }

我们再次启动服务,初次访问localhost:${port}/student_refresh得到如下内容:

Student(name=mac, age=null, classNo=null, className=null)

接下来通过Nacos后台界面修改内容如下:

student:
 name: tom
 age: 18

再次访问链接得到如下内容:

Student(name=tom, age=18, classNo=null, className=null)

从结果可以看出,刚刚在Nacos后台修改的配置即使应用不重启也刷新生效了。

配置Data Id

默认Data Id

在先前的示例中,我们在Nacos中填写的Data Id格式为${spring.application.name}.${file-extension},如果我们不填写后面的file-extension也是可以的,但是Nacos管理后台中选择的配置格式必须跟bootstrap.ymlspring.cloud.nacos.config.file-extension保持一致。

也就是说我们可以将之前的配置文件名nacos-config.yaml修改为nacos-config

基于Profile粒度配置

在实际开发中我们可能根据环境来应用配置文件。例如在开发环境中,我们创建配置文件application-dev.yml,而在测试环境中我们使用application-test.yml,而最后通过spring.profiles.active应用哪一个配置文件。同样,在Nacos中也支持该特性,它可以根据profile的值来应用对应的配置文件。它的应用格式如下:

${spring.application.name}-${profile}.${file-extension}

现在我们创建两个配置文件nacos-config-dev.yamlnacos-config-test.yaml,其内容分别如下:

student:
 class-no: dev
student:
 class-no: test

接下来我们在bootstrap.yml中增加如下配置:

spring:
  profiles:
    active: dev

接下来重新启动应用,再次访问localhost:${port}/student_refresh,得到结果如下:

Student(name=tom, age=18, classNo=dev, className=null)

从结果可以看出,配置文件nacos-config.yamlnacos-config-dev.yaml都生效了,关于属性值覆盖稍后再讲解。

自定义Data Id配置

通过上面我们已经知道了默认Data Id和基于profile的Data Id,同时还支持自定义Data Id配置。接下来我们在Nacos管理后台创建Data Idnacos-config-extension-configs-1.yaml的配置,配置内容如下:

student:
 class-name:  nacos-config-extension-configs-1.yam

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

spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      config:
        extension-configs:
          - data-id: nacos-config-extension-configs-1.yaml

同时它还支持另外两个属性grouprefresh,默认情况下refresh为false,也就是不支持动态刷新。需要注意的是,extension-configs是一个数组,它支持配置多个。

该方式最后的file-extension不能省略。

同样Nacos还支持另外一种方式来自定义配置文件,extension-configs通常用在同一应用不同实例共享配置,而shared-configs则用在不同应用共享同一配置。例如在orderstore服务中,不同的order实例使用extension-configs来共享配置,而orderstore不同应用通过shared-configs来共享配置。

在Nacos后台中创建nacos-config-shared-configs-1.yaml配置文件,其配置内容如下:

student:
 ext-pro: nacos-config-shared-configs-1.yaml男

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

spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      config:
        shared-configs:
          - data-id: nacos-config-shared-configs-1.yaml

最后在Student类中增加extPro属性,重启应用再次刷新链接得到如下内容:

Student(name=tom, age=18, classNo=dev, className=nacos-config-extension-configs-1.yam, extPro=nacos-config-shared-configs-1.yaml)

属性值覆盖问题

前面介绍了Nacos各种配置文件的配置方式,但是存在一个问题就是不同的配置文件中可能会存在相同的配置,那么这些配置哪个会生效呢?下面我们通过以下几种情况来分析。

远程加载配置和本地application.yml

首先我们删除Nacos后台的所有配置文件,然后创建配置文件nacos-config.yaml,其内容如下:

student:
 name: tom
 age: 18

然后在本地应用中创建配置文件其内容如下:

student:
  name: tom
  age: 18
  class-no: c2
  class-name: 二班
  ext-pro: 扩展

最后运行结果如下:

Student(name=tom, age=18, classNo=c2, className=二班, extPro=扩展)

通过结果可以发现,通过远程加载的配置文件其属性值会覆盖本地application.yml中的配置属性值

默认Data Id

默认情况下支持三种属性配置文件,它们分别为:

  • ${spring.application.name},例如nacos-config

  • ${spring.application.name}.${file-extension},例如nacos-config.yaml

  • ${spring.application.name}-${profile}.${file-extension},例如nacos-config-dev.yaml

对于上面三种配置文件,其优先级根据上面的顺序越来越高。其实这一点可以通过源码看出,其源码位于NacosPropertySourceLocator中:

 private void loadApplicationConfiguration(
   CompositePropertySource compositePropertySource, String dataIdPrefix,
   NacosConfigProperties properties, Environment environment)
 
{
  String fileExtension = properties.getFileExtension();
  String nacosGroup = properties.getGroup();
  // load directly once by default
  loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
    fileExtension, true);
  // load with suffix, which have a higher priority than the default
  loadNacosDataIfPresent(compositePropertySource,
    dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
  // Loaded with profile, which have a higher priority than the suffix
  for (String profile : environment.getActiveProfiles()) {
   String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
   loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
     fileExtension, true);
  }

 }

从源码已经其中的注释可以看出,其优先级就是顺序就是profile最高,接着就是指定了file-extension的,最后就是默认的。

自定义Data Id配置

对于通过shared-configsextension-configs加载的配置文件,其优先级要低于约定的Data Id的配置,也就是通过应用名+profile自动加载的配置文件。

shared-configs的优先级则低于extension-configs

对于自定义的Data Id配置,它们都支持同时配置多个。对于同一类型的多个,如果是通过properties方式配置的,例如:

spring.cloud.nacos.config.shared-configs[0].data-id=common-0.yaml
spring.cloud.nacos.config.shared-configs[1].data-id=common-1.yaml

其中shared-configs[n]的n越大,其优先级越高。而对于像yaml这样的配置,越排在后面的配置其优先级越高。例如下面的配置:

spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      config:
        extension-configs:
          - data-id: nacos-config-extension-configs-1.yaml
          - data-id: nacos-config-extension-configs-2.yaml

其中nacos-config-extension-configs-2.yaml优先级大于nacos-config-extension-configs-1.yaml

小结

以上就是使用Nacos作为统一配置中心的所有示例了。如果有部分不太清楚的部分可以通github官方wiki查看相关内容,其文档地址如下:

https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config

本文的示例工程代码地址:

https://github.com/I-Like-Pepsi/spring-cloud-alibaba-demo


往期相关文章:

SpringCloud Alibaba版本教程-开始

Spring Cloud Alibaba版本教程-Nacos服务注册和发现


原文始发于微信公众号(一只菜鸟程序员):SpringCloud Alibaba版本教程-Nacos统一配置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72788.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!