Spring Cloud Alibaba Nacos 配置中心

417 阅读4分钟

前言

配置中心,最早的时候用过360的QConf,后来又用过一阵子携程的Apollo,最近这2年用的都是阿里的Nacos

QConf的技术路线独辟蹊径,之前在PHP的项目里用的很舒服。但毕竟不属于Java技术栈上的产品,后来Java团队技术选型的时候也就没再沿用它。写文章的时候看了一眼QConf的GitHub主页,最后一次更新还是2017年的时候了。

Nacos作为阿里云原生环境下的配置中心,应该是目前最有前途的配置中心了。Nacos基于阿里云庞大的用户群可以获取大量的反馈,产品也就能打磨的越来越好。

环境准备:

服务端

本机安装Nacos参考官网就好了,启动一个单机版的实例就够开发测试用了。阿里云托管的Nacos在阿里云的MSE板块下面。

客户端

全家桶的版本配置,参考这里的版本关系,选择的是Spring Boot 2.6的版本。版本的不同影响还挺大的,后面再细说。

<properties>  
    <spring-boot.version>2.6.13</spring-boot.version>  
    <spring-cloud.version>2021.0.5</spring-cloud.version>  
    <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>  
</properties>

增加Nacos的依赖项:

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

注意: 由于spring-cloud-starter-alibaba-nacos-config移除了spring-cloud-starter-bootstrap依赖。现在推荐使用 spring.config.import 方式引入配置。你在网上找到的大部分文章都在介绍怎么在bootstrap.yml里配置nacos,但是现在你需要换成application.yml了:

说一句题外话: 把配置文件统一成yml格式吧,不仅覆盖Properties格式的所有功能,结构还更清晰。

# application.yml
nacos:
  server-addr: 127.0.0.1:8848
  username: nacos
  password: 5j@Tc3fbgeE@TRi
  namespace: 075fc053-5a4e-4785-9f3d-638d86d76b1f

spring:
  cloud:
    nacos:
      # 当nacos客户端的配置中nacos.core.auth.enabled=true时,username、password不能省略
      username: ${nacos.username}
      password: ${nacos.password}
      config:
        file-extension: yml
        refresh-enabled: true
        server-addr: ${nacos.server-addr}
        namespace: ${nacos.namespace}
  config:
    import:
      - optional:nacos:${spring.application.name}.${spring.cloud.nacos.config.file-extension}

最下面这行import就是引入nacos配置文件的,如果没有这一行会报错:

***************************
APPLICATION FAILED TO START
***************************

Description:

The spring.config.import property is missing a nacos: entry

Action:

Add a spring.config.import=nacos: property to your configuration.
	If configuration is not required add spring.config.import=optional:nacos: instead.
	To disable this check, set spring.cloud.nacos.config.import-check.enabled=false.

客户端动态获取配置中心的值

@RestController  
@RequestMapping("/nacos-config")  
@RefreshScope  
public class NacosConfigController {  
    @Value("${welcome.message}")  
    private String welcomeMessage;  

    @GetMapping("/welcome")  
    public String showWelcome() {  
        return this.welcomeMessage;  
    }
}

使用@Value("${}")注解跟获取本地参数一样的方式获取远端配置中心的值。加上@RefreshScope注解保证配置可以实时更新

插播一段小插曲: 之前在测试的时候,我在Nacos的yml配置文件里设置的变量名正好是user.name。结果代码里获取的变量始终是登陆系统的用户名,不管怎么改Nacos配置甚至重启Nacos都不生效。倒腾好一阵子,才发现user.name是Java的系统变量,而且它的加载顺序是晚于配置文件的加载的,所以无论在Nacos里面怎么改,最后都会被系统变量所覆盖。

Nacos的几个概念

  • Namespace
  • Data ID
  • Group

如果你在网上看过几篇介绍Nacos使用的文章,你肯定看到过类似这样的话:同一个应用在不同环境下的配置,通过namespace来做环境隔离。比如开发环境的namespace命名为dev,测试环境的namespace命名为test,线上环境的namespace命名为prod。

我不知道真正有多少公司是这样使用namespace的。在我工作过的环境里,测试环境和线上环境的网络都是不通的,更不会用一套配置中心来支持多个环境,而是测试环境是测试的Nacos集群,线上环境是线上的Nacos集群。应用通过启动参数spring.profiles.active=<profile>来指定使用不同的配置文件,进而连接到不同的集群。

我们把Namespace用来标志业务域。比如order,goods,passport这样。而Data ID,我们让它跟服务名称保持一样。至于Group,用的就是DEFAULT_GROUP,没改过。

一个容易踩坑的小点:配置文件里指定的Namespace,应该是你在Nacos控制台上看到的那个ID,也就是下图红框里的部分,而不是绿框里的。

WechatIMG178.jpg

至于在过去的版本里讨论的extension-configs,shared-configs的优先级和使用问题。貌似也不用过多的考(背)虑(诵)了。直接在spring.config.import里面一个个的往后加就完了

spring:
  cloud:
    nacos:
      # 当nacos客户端的配置中nacos.core.auth.enabled=true时,username、password不能省略
      username: ${nacos.username}
      password: ${nacos.password}
      config:
        file-extension: yml
        refresh-enabled: true
        server-addr: ${nacos.server-addr}
        namespace: ${nacos.namespace}
  config:
    import:
      - optional:nacos:${spring.application.name}.${spring.cloud.nacos.config.file-extension}
      - optional:nacos:mysql-config.yml?group=datasource
      - optional:nacos:redis-config.yml?group=datasource&refreshEnabled=false