Spring Boot 本地联调:复用 Nacos test 配置并单独连接 dev 数据库

问题背景

在基于 Spring Boot 和 Spring Cloud Alibaba Nacos 的项目中,本地启动服务时经常会遇到这样的需求:

  • 本地没有一套完整的 dev 配置;
  • 服务仍需从 Nacos 的 test 命名空间读取公共配置;
  • 本地需要发现并调用 test 环境中的其他服务;
  • 数据库必须连接 dev,不能误操作 test 数据;
  • 本机实例不能影响 test 环境的正常流量。

看起来只需要修改数据库地址,但实际涉及三个相互独立的概念:

  1. Spring Profile:决定当前应用加载哪套环境配置。
  2. Nacos namespace:决定从哪个配置和服务环境读取数据。
  3. Nacos 服务注册:决定其他服务是否能把请求路由到本机。

正确思路是:使用独立的 dev Profile,让它连接 test Nacos、复用 test 公共配置,再通过应用级 dev 配置覆盖数据库,同时禁止本机实例注册。

适用场景

本文方案适用于以下项目:

  • Spring Boot 应用;
  • 使用 Nacos Config 和 Nacos Discovery;
  • test 环境中的公共配置仍可供本地开发使用;
  • 本地需要连接独立的 dev 数据库;
  • 数据源使用普通 Spring DataSource 或动态数据源。

不同版本的 Spring Cloud Alibaba 可能存在配置加载方式差异,应用前应结合项目实际依赖确认 Data ID 的加载顺序。

为什么不能直接使用 test Profile

如果直接用 test Profile 启动,本地服务通常会自动加载:

application-test.yml
<service-name>-test.yml

这些配置往往包含 test 数据库连接,因此本地服务也会连接 test 数据库。

一种直观做法是在 IDEA 启动参数中直接覆盖数据库配置。对于配置简单的项目,这种方式可能有效;但当项目大量依赖 Nacos 远端配置时,还需要考虑远端配置和本地配置的优先级。配置来源越多,越容易出现“参数已经填写,实际连接的仍是 test 数据库”的情况。

更清晰的方案是为本地联调使用 dev Profile,同时显式复用 test 配置。

配置结构

最终的配置关系如下:

IDEA
└── 激活 dev Profile
    └── bootstrap-dev.yml
        ├── 连接 test Nacos
        ├── 使用 test namespace
        └── 加载 test 公共配置
            ├── application-test.yml
            └── <service-name>-test.yml
                └── <service-name>-dev.yml
                    ├── 覆盖 dev 数据源
                    └── 禁止本机服务注册

这样可以把“使用哪个 Profile”和“连接哪个 Nacos 环境”解耦。

配置 bootstrap-dev.yml

在项目中增加本地 dev 环境的引导配置:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: <nacos-host>:8848
        namespace: <test-namespace-id>

      config:
        server-addr: <nacos-host>:8848
        namespace: <test-namespace-id>
        file-extension: yml
        shared-configs:
          - data-id: application-test.yml
            refresh: false
          - data-id: <service-name>-test.yml
            refresh: false

这里需要注意两点。

第一,namespace 应填写 Nacos 中实际的命名空间标识,不要根据控制台显示名称猜测。

第二,只加载 application-test.yml 可能不够。很多项目还会在 <service-name>-test.yml 中维护 MyBatis、中间件或业务模块配置。切换为 dev Profile 后,这份应用级 test 配置通常不会自动继承,因此应根据项目实际情况显式加入共享配置。

使用应用级 dev 配置覆盖数据库

当前 Profile 为 dev 时,Nacos 会按应用名尝试加载:

<service-name>-dev.yml

可以在 test 命名空间中增加这份配置,只维护本地 dev 环境需要覆盖的内容。

以动态数据源为例:

spring:
  cloud:
    nacos:
      discovery:
        register-enabled: false

  datasource:
    dynamic:
      datasource:
        master:
          url: jdbc:mysql://<dev-host>:3306/<dev-database>?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: <dev-user>
          password: <dev-password>
          driver-class-name: com.mysql.cj.jdbc.Driver

如果项目使用普通 Spring 数据源,对应配置可以调整为:

spring:
  datasource:
    url: jdbc:mysql://<dev-host>:3306/<dev-database>?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: <dev-user>
    password: <dev-password>
    driver-class-name: com.mysql.cj.jdbc.Driver

公开文档、代码仓库和聊天记录中不应出现真实的数据库地址、库名、账号或密码。实际使用时,也应按照团队的凭据管理规范保存敏感配置。

IDEA 启动配置

在 IDEA 中按以下步骤配置:

  1. 点击右上角运行配置下拉框。
  2. 选择 Edit Configurations…。
  3. 选择当前 Spring Boot 启动类对应的运行配置。
  4. 点击 Modify options。
  5. 启用 Add VM options。
  6. 在 VM options 中填写:
-Dspring.profiles.active=dev
  1. 点击 Apply 和 OK,然后重新启动服务。

不要把上述写法直接放进 Program arguments。两种参数位置对应的语法不同:

VM options:

-Dspring.profiles.active=dev

Program arguments:

--spring.profiles.active=dev

两者选择一种即可,避免同时配置造成排查困难。

启动后,日志中应出现类似信息:

The following 1 profile is active: "dev"

如果日志仍显示 test,通常说明修改的不是当前实际运行的 IDEA 配置,或者其他启动参数覆盖了该值。

为什么要禁止本机实例注册

本地服务连接 test Nacos,不代表必须注册到 test 服务列表。

如果允许本机实例注册,test 环境中的其他服务可能通过负载均衡把真实测试请求发送到开发者电脑。这会带来多种问题:

  • 本机代码可能处于未完成状态;
  • 本机端口可能无法被 test 网络访问;
  • 电脑休眠或断网会造成调用失败;
  • 本地调试行为可能改变 test 环境的业务结果。

因此,本方案设置:

spring:
  cloud:
    nacos:
      discovery:
        register-enabled: false

关闭注册后,本地服务仍然可以从 test Nacos 发现并调用其他服务,但不会成为 test 环境中的服务提供者。

如果业务场景确实要求 test 服务反向调用本机,则应使用单独的联调方案,并明确处理网络连通、实例隔离和流量标识问题。

如何验证配置是否真正生效

仅看到应用启动成功还不够,应分别验证 Profile、Nacos、服务注册和数据库。

1. 检查 Profile

确认启动日志显示:

The following 1 profile is active: "dev"

2. 检查配置加载

确认应用加载了预期的配置:

application-test.yml
<service-name>-test.yml
<service-name>-dev.yml

其中:

  • test 配置提供公共能力;
  • dev 配置只覆盖本地差异;
  • 数据源最终值应来自 dev 配置。

3. 检查服务注册

在 Nacos 控制台查看对应服务的实例列表,确认本机地址没有出现在 test 实例中。

4. 检查数据库

在不修改业务数据的前提下执行安全的只读查询,确认实际数据库为预期的 dev 库。例如:

SELECT DATABASE();

不要只根据配置文件判断连接目标。应用最终使用的属性可能受到启动参数、本地文件、共享配置和应用级 Nacos 配置共同影响。

5. 检查 test 环境

确认 test 环境中的原有服务实例、数据库配置和调用链均未发生变化。

不要忽略其他外部资源

数据库切换到 dev 后,并不代表整个应用已经与 test 环境隔离。

复用 test 公共配置时,下面这些资源仍可能指向 test:

  • Redis;
  • 消息队列;
  • 定时任务;
  • 文件存储;
  • 搜索服务;
  • 第三方接口;
  • 缓存和分布式锁。

如果本地服务会消费消息、发送通知或执行定时任务,应根据项目提供的开关关闭相关功能,或为它们配置独立的开发环境资源。

可复用经验

这次配置问题可以总结为几条通用经验:

  1. Spring Profile、Nacos namespace 和服务注册是三个独立维度,不应混为一谈。
  2. 本地联调应使用独立 Profile 描述本地差异,而不是直接修改共享的 test 配置。
  3. 环境覆盖文件只保留必要差异,避免复制整套远端配置。
  4. 切换 Profile 后,要检查应用级 Data ID 是否仍被正确加载。
  5. 禁止本机实例注册,可以显著降低对共享测试环境的影响。
  6. 判断数据库是否切换成功,应以实际只读查询结果为准。
  7. 数据库之外的 Redis、MQ 和定时任务同样需要检查,避免跨环境操作。

通过这种配置方式,本地服务可以继续复用 test Nacos 提供的配置和服务发现能力,同时使用独立的 dev 数据库,并避免本机实例干扰 test 环境。