Consul 配置踩坑:数据源切换的陷阱与排查

数字孪生模块从 local profile 切换到 Consul 配置后,视频巡查接口全部报 500:Table 'gdsw.bs_sw_cy_dh_video_inspection' doesn't exist。本地库有这张表,MCP 工具能查到,但服务连不上。本文记录了这个坑的根因、排查思路和解决方案。

🎧 文章导读

🎵 背景音乐

问题现象

数字孪生模块(digital-twin)从 local profile 切换到 Consul 配置后,视频巡查接口全部报 500:

1
Table 'gdsw.bs_sw_cy_dh_video_inspection' doesn't exist

奇怪的是,本地数据库确实有这张表,用 MCP 工具能正常查询。但服务就是连不上。

排查过程

第一步:确认表是否存在

用 MCP 工具直接查询本地数据库,确认 bs_sw_cy_dh_video_inspection 表存在且有数据。

结论:表存在,问题不在数据库。

第二步:怀疑服务连错了数据库

既然表存在但服务报”表不存在”,最可能的原因是服务连的不是同一个数据库

查看启动日志,发现数据源初始化的 URL 是 10.144.32.219:3306/gdsw(远程库),而不是 127.0.0.1:3306/gdsw(本地库)。

结论:服务连的是远程库,远程库没有新建的表。

第三步:检查 Consul 配置

Consul 配置分两层:

1
2
3
4
5
6
7
Consul 配置中心
├── 通用模板(gdsw-common-config)
│ └── spring.datasource.url → 远程库 10.144.32.219
├── 数字孪生模块(gdsw-digital-twin-config)
│ └── targetdatabase.url → 本地库 127.0.0.1(自定义配置项)
└── 数据归集模块(gdsw-data-collection-config)
└── 模块专属配置

问题根因:模块配置中使用了自定义配置项 targetdatabase.url,但这个配置项不会覆盖 Spring 的 spring.datasource.url。实际数据源用的是通用模板里的远程库地址。

根因分析

Consul 配置的覆盖规则是:模块级配置覆盖通用模板的同名属性

targetdatabase.url 是自定义配置项,不是 Spring 数据源的标准配置项。Spring Boot 自动配置数据源时,读取的是 spring.datasource.url,而不是 targetdatabase.url

1
2
3
4
5
6
7
8
# 通用模板(所有模块共享)
spring:
datasource:
url: jdbc:mysql://10.144.32.219:3306/gdsw # 远程库

# 数字孪生模块配置
targetdatabase:
url: jdbc:mysql://127.0.0.1:3306/gdsw # 自定义配置项,不会覆盖 spring.datasource.url

所以实际数据源用的是通用模板的远程库地址,远程库没有新建的表,导致 Table doesn't exist

解决方案

在数字孪生模块的 Consul 配置中,直接覆盖 spring.datasource

1
2
3
4
5
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/gdsw?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: root
password: root

这样模块级配置的 spring.datasource.url 会覆盖通用模板的同名属性,服务就会连本地库。

注意事项

1. YAML 不能有两个同级 spring:

1
2
3
4
5
6
7
# 错误:两个 spring: 块,后面的覆盖前面的
spring:
servlet:
multipart: ...
spring: # ← 这个会覆盖上面的
datasource:
url: ...
1
2
3
4
5
6
7
8
9
# 正确:合并成一个 spring: 块
spring:
servlet:
multipart: ...
datasource:
url: ...
dynamic:
datasource:
slave: ...

2. 数据库配置改了必须重启

@RefreshScope 热更新不了连接池。数据库连接池在应用启动时初始化,运行时修改配置不会生效。

3. 普通业务配置可以热更新

开关、URL、TTL 等普通业务配置可以通过 @RefreshScope 热更新,不用重启。

Consul 配置结构理解

配置层级图
图1:Consul 配置的三层结构

1
2
3
4
5
6
7
8
Consul 配置中心
├── 通用模板(gdsw-common-config)
│ └── 定义所有模块共享的默认配置
├── 数据归集模块(gdsw-data-collection-config)
│ └── 覆盖数据归集模块的专属配置
├── 数字孪生模块(gdsw-digital-twin-config)
│ └── 覆盖数字孪生模块的专属配置
└── 其他模块...

覆盖规则:模块级配置 > 通用模板 > 本地配置文件

关键点:只有同名属性才会被覆盖。自定义配置项(如 targetdatabase.url)不会影响 Spring 的标准配置项(如 spring.datasource.url)。

排查思路总结

排查流程图
图2:问题排查的五步流程

  1. Table doesn't exist → 先确认表是否真的不存在
  2. MCP 能查到但服务报错 → 服务连的不是同一个数据库
  3. 看启动日志里数据源初始化的 URL
  4. 检查 Consul 配置里 spring.datasource 的实际值
  5. 注意自定义配置项不会影响 Spring 标准配置项

经验总结

  1. 自定义配置项不能替代 Spring 标准配置项——targetdatabase.url 不会覆盖 spring.datasource.url
  2. 模块级配置要覆盖同名属性——想切换数据源,必须覆盖 spring.datasource.url
  3. 数据库配置改了必须重启——@RefreshScope 热更新不了连接池
  4. YAML 不能有两个同级 spring:——会冲突覆盖,需要合并
  5. 排查问题要从数据源开始——“表不存在”往往是连错了库

本文记录于 2026-05-29,数字孪生模块 Consul 配置踩坑。