整合Nacos配置中心编码实践

本节笔者讲解如何在应用程序中整合 Nacos 配置中心,并从 Nacos 配置中心获取配置项。

创建基础工程

在整合 Nacos 配置中心前,先编写一个简单的微服务工程,在这个工程中使用配置文件的方式存放工程启动时的配置项,之后以该工程为基础去整合 Nacos 配置中心。这样读者在学习时就可以更好地理解 Nacos 配置中心的整合过程,也能将两种配置方式进行对比。

该工程是在 spring-cloud-alibaba-nacos-demo 项目的基础上修改的,具体修改步骤如下。

先修改项目名称为 spring-cloud-alibaba-nacos-config-base-demo,把项目根目录下 pom.xml 文件的 artifactId 修改为 spring-cloud-alibaba-nacos-config-base-demo

然后将原来的 nacos-provider-demo 模块的名称修改为 nacos-config-demo,并将该模块的 parent 标签修改为 spring-cloud-alibaba-nacos-config-base-demo,与上层 Maven 建立好关系。在这个子模块的 pom.xml 文件中加入连接 MySQL 数据库所需的依赖。子节点 nacos-provider-demopom.xml 源码如下:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ltd.newbee.cloud</groupId>
    <artifactId>nacos-config-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nacos-config-base-demo</name>
    <description>Spring Cloud Alibaba Nacos Base Demo</description>

    <parent>
        <groupId>ltd.newbee.cloud</groupId>
        <artifactId>spring-cloud-alibaba-nacos-config-base-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
</project>

接着在 nacos-config-demo 中进行简单的功能编码,把该 Spring Boot 项目的启动类名称修改为 ConfigApplication,并在 ltd.newbee.cloud.api 包中新建 TestController 类,代码如下:

package ltd.newbee.cloud.api;

import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.sql.Connection;
import javax.sql.SQLException;
import java.util.Properties;

@RestController
public class TestController {

    @Resource
    private DataSource dataSource;

    @GetMapping("/dataSource")
    public String dataSource() throws SQLException {
        String dataSourceClass = dataSource.getClass().toString();
        Boolean haveConnection = dataSource.getConnection() == null ? false : true;
        return "数据源类型: " + dataSource + ", 是否连接成功: " + haveConnection + "";
    }
}

该测试类主要验证数据源类型,以及是否获取正确的数据库连接。最后在配置文件中添加服务名称、注册中心配置、数据库连接配置等内容,最终的 application.properties 文件代码如下:

# 服务名称
spring.application.name=newbee-cloud-config-service

# 环境配置 (dev 表示开发环境)
spring.profiles.active=dev

# 端口号
server.port=8094

# Nacos 注册中心地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
# Nacos 用户名 (默认为 nacos,生产环境一定要修改)
spring.cloud.nacos.username=nacos
# Nacos 登录密码 (默认为 nacos,生产环境一定要修改)
spring.cloud.nacos.password=nacos

# datasource config (MySQL)
spring.datasource.name=newbee-mall-cloud-user-datasource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/newbee_mall_cloud_user
?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&
autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.pool-name=hikariCP
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

最终的工程目录结构如图 6-28 所示。

image 2025 04 16 14 04 13 695
Figure 1. 图6-28 最终的工程目录结构

该项目是整合配置中心前的基础代码,主要是创建一个包含常用配置项的微服务架构实例,配置中包含项目的基础配置项、注册中心配置项及数据源配置项。启动 ConfigApplication 主类,如果项目在启动过程中没有报错,并且注册中心已经出现 newbee-cloud-config-service 服务,访问 /dataSource 地址也能获取正确的数据库连接信息,则表示编码成功。

集成 Nacos 配置中心

下面笔者以 spring-cloud-alibaba-nacos-config-base-demo 项目为基础讲解如何在应用程序中整合 Nacos 配置中心获取配置项,之后实现动态配置项刷新。

添加 Nacos Config 依赖

打开 nacos-config-demopom.xml 文件并添加以下两个依赖项:

<!-- 配置中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 读取 bootstrap -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

项目的配置文件中通常包括数据库连接配置项、日志输出配置项、Redis 连接配置项、服务注册配置项等内容,如 spring-cloud-alibaba-nacos-config-base-demo 项目中就包含数据库连接配置项和服务注册配置项。如果把这些配置项存放在配置中心,为了保证项目能够正常启动,就必须在数据源实例配置、服务注册流程之前读到所有配置项,因为类似数据源、日志工厂等实例的初始化和服务注册流程都是在项目启动过程中进行的。

基于这个原因,在服务的启动阶段就需要将连接 Nacos 配置中心的配置项加载优先级设置为最高。在 Spring Boot 规范中,bootstrap 配置文件(bootstrap.ymlbootstrap.properties)用来引导程序时执行,应用于更加早期的配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的,其加载优先级高于 application 配置文件(application.ymlapplication.properties)。将连接 Nacos 配置中心的配置项放到 bootstrap 文件中,能够确保在启动阶段优先读取 Nacos 配置中心里存储的配置项。

添加完依赖,接下来就要配置连接 Nacos 配置中心的参数了。

代码中配置Nacos Config连接参数

先在 nacos-config-demo 模块的 resource 目录下创建 bootstrap.properties 配置文件。

然后在 bootstrap.properties 文件中添加一些连接 Nacos 配置中心的参数,代码及参数释义如下:

# 服务名称
spring.application.name=newbee-cloud-config-service

# 环境配置(dev表示开发环境)
spring.profiles.active=dev

# Nacos 配置中心地址
spring.cloud.nacos.config.server-addr=localhost:8848
# 命名空间默认为 PUBLIC
spring.cloud.nacos.config.namespace=dev
# 配置分组默认为 DEFAULT_GROUP
spring.cloud.nacos.config.group=NEWBEE_CLOUD_DEV_GROUP
# 配置文件格式(参数有 yml、json、properties 等)
spring.cloud.nacos.config.file-extension=properties
# Nacos 配置中心登录用户名(默认为 nacos,生产环境一定要修改)
spring.cloud.nacos.config.username=nacos
# Nacos 配置中心登录密码(默认为 nacos,生产环境一定要修改)
spring.cloud.nacos.config.password=nacos

添加配置文件到Nacos配置中心

打开浏览器并进入 Nacos 控制台页面,如果没有配置自定义命名空间,就可以单击左侧导航栏中的 “命名空间” 按钮,打开 “新建命名空间” 对话框,配置内容如图 6-29 所示。

image 2025 04 16 14 12 27 995
Figure 2. 图6-29 “新建命名空间”对话框

在 “新建命名空间” 对话框中主要设置命名空间ID、命名空间名和描述。其中,命名空间 ID 就是连接配置中心的 spring.cloud.nacos.discovery.namespace 配置项和连接服务注册中心的 spring.cloud.nacos.config.namespace 配置项所要填写的值,笔者将其设置为 dev。如果不设置,则会自动生成一个长度为 36 个字符的字符串。配置完成后的命名空间列表页面如图 6-30 所示。

image 2025 04 16 14 13 13 368
Figure 3. 图6-30 命名空间列表页面

单击左侧导航栏中的 “配置列表” 按钮,再切换到 “开发环境” 命名空间(dev),如图 6-31 所示。

image 2025 04 16 14 18 44 643
Figure 4. 图6-31 切换命名空间

单击配置管理页面右侧的 “+” 按钮,可以新建一项配置。在这里可以把原来在 application.properties 文件中的配置项存储到 Nacos 配置中心。“新建配置” 页面如图 6-32 所示。

image 2025 04 16 14 19 20 535
Figure 5. 图6-32 “新建配置”页面

“新建配置” 页面包含 7 个选项:Data IDGroup、标签、归属应用、描述、配置格式和配置内容,重要的选项释义如下。

  1. Data ID:配置的唯一标识,必填项。

  2. Group:指定配置文件的分组,这里设置默认分组 DEFAULT_GROUP 即可,必填项。

  3. 描述:说明配置文件的用途,可不填。

  4. 配置格式:指定 “配置内容” 的类型(文件后缀名),必填项。

  5. 配置内容:程序运行所需的配置项列表,必填项。

在 “新建配置” 页面中,笔者指定了 Data IDnewbee-cloud-config-service-dev.propertiesGroup 为自定义分组 NEWBEE_CLOUD_DEV_GROUP、配置格式为 Properties。在 “配置内容” 文本框中,笔者将端口号、注册中心连接配置项和数据库连接配置项添加了进去。

Data ID详解

Data IDNacos 配置中心里是配置项的唯一标识符,用于标识一个配置项信息,并在客户端获取配置信息时使用。

组成 Data ID 的完整参数如下:

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

其中,${prefix} 默认为应用名称,即 spring.application.name 配置项的值;${spring.profiles.active} 是当前选择的环境;${file-extension} 是配置内容的数据格式,即配置文件的后缀名。

当前项目的 bootstrap.properties 文件中已经对上述三个配置项做了配置:

# 服务名称
spring.application.name=newbee-cloud-config-service

# 环境配置 (dev 表示开发环境)
spring.profiles.active=dev

# 配置文件格式 (参考有 yml、json、properties 等)
spring.cloud.nacos.config.file-extension=properties

因此,在拉取配置中心的配置时所读取的 Data ID 就是 newbee-cloud-config-service-dev.properties,这也是在 “新建配置” 页面中笔者将 Data ID 指定为 newbee-cloud-config-service-dev.properties 的原因,并不是随意输入的。如果在 Data ID 中输入了其他字符串,则程序无法通过配置中心拉取正确的配置,启动阶段会直接报错。

如果 spring.profiles.active 配置项并未指定,则对应的连接符 “-” 也没了,Data ID 的组成参数会变成 ${prefix}.${file-extension}。比如,本节中的演示代码,如果不指定 spring.profiles.active 配置项,则 Data ID 就是 newbee-cloud-config-service-dev.properties

另外,若不想使用应用名称作为 prefix,可以使用 spring.cloud.nacos.config.prefix 进行自定义。比如,本节中的演示代码如果增加了一个配置项:

# 服务名称
spring.application.name=newbee-cloud-config-service

# 自定义 Data ID 前缀
spring.cloud.nacos.config.prefix=config-service

# 环境配置 (dev 表示开发环境)
spring.profiles.active=dev

# 配置文件格式 (参考 yml, json, properties 等)
spring.cloud.nacos.config.file-extension=properties

那么 Data ID 就是 config-service-dev.properties。如果在 Nacos 配置中心没有新建 config-service-dev.properties,则程序在启动时无法拉取配置信息,会直接报错。

整合Nacos配置中心功能验证

一切设置妥当之后,就可以启动应用程序进行功能验证了。同时,为了测试应用程序能否正确拉取配置中心所创建的远程配置项,可以删除原来项目中的 application.properties 文件。

启动 nacos-config-demo 项目(需保证 Nacos Server 和 MySQL Server 已经正常运行)。若启动过程中没有报错,则启动日志如下:

image 2025 04 16 14 25 23 029

打开浏览器,输入如下请求地址:

http://localhost:8094/dataSource

浏览器输出的内容如下:

image 2025 04 16 14 26 21 994

进入 Nacos 控制台页面,可以看到该服务已经出现在 “服务列表” 页面中了,如图 6-33 所示。

image 2025 04 16 14 26 47 064
Figure 6. 图6-33 Nacos 控制台中的“服务列表”页面

有些读者可能会问:服务怎么会注册到 public 命名空间?

这是因为笔者在服务注册的相关配置中并没有对 spring.cloud.nacos.discovery.namespacespring.cloud.nacos.discovery.group 两个参数赋值,而是直接使用了它们的默认值,因此 newbee-cloud-config-service 会注册在 public 命名空间且分组名称为 DEFAULT_GROUP。笔者在 bootstrap.properties 文件中指定的是程序与配置中心的连接参数,命名空间和分组的配置名称分别是 spring.cloud.nacos.config.namespacespring.cloud.nacos.config.group,配置项名称不同,作用也不同,读者一定要注意区分。

不仅是这几条配置项容易混淆,初学者在引入 Nacos 依赖项时也容易搞混。Nacos 组件既可以作为微服务架构中的服务注册中心,也可以作为配置中心。引入 Nacos 的服务发现功能,需要添加 spring-cloud-starter-alibaba-nacos-discovery 包;而引入 Nacos 的配置管理功能,需要添加 spring-cloud-starter-alibaba-nacos-config 包。读者一定要注意这些微小的差别,不要弄错了。

到这里,功能验证的结果就出来了。整合 Nacos 配置中心后,项目能够正常启动,数据库连接成功,服务也正确地注册到 Nacos Server。这些都表明整合成功,程序能够正确地通过 Nacos 配置中心远程拉取配置内容。