From d11ed1ba1ea96796c34e4b75368bd716386aaf17 Mon Sep 17 00:00:00 2001 From: zhangjf Date: Thu, 19 Feb 2026 18:26:28 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E9=97=AE=E9=A2=9810?= =?UTF-8?q?=20HikariMonitorConfig=E7=A9=BA=E6=8C=87=E9=92=88=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=88=B0=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/开发问题清单.md | 74 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/doc/开发问题清单.md b/doc/开发问题清单.md index 84dfb71..cbd277e 100644 --- a/doc/开发问题清单.md +++ b/doc/开发问题清单.md @@ -19,6 +19,7 @@ | 7 | 全链路追踪 | TraceContextHolder未在HTTP入口初始化导致链路断裂 | 高 | 已解决 | | 8 | OpenFeign配置 | FeignClient硬编码URL导致Nacos服务发现失效 | 高 | 已解决 | | 9 | Nacos 配置 | Nacos 3.0 客户端缺少 username/password 认证配置 | 高 | 已解决 | +| 10 | 连接池监控 | HikariMonitorConfig空指针异常 | 中 | 已解决 | --- @@ -594,6 +595,77 @@ curl http://localhost:8000/sys/api/v1/sys/health --- +### 问题 10:HikariMonitorConfig 空指针异常 + +#### 问题现象 +服务启动后,定时任务日志中持续报错: +``` +java.lang.NullPointerException: Cannot invoke "com.zaxxer.hikari.HikariPoolMXBean.getActiveConnections()" because the return value of "com.zaxxer.hikari.HikariDataSource.getHikariPoolMXBean()" is null + at com.fundplatform.sys.config.HikariMonitorConfig.monitorHikariPool(HikariMonitorConfig.java:38) +``` + +#### 问题原因 +**HikariCP 连接池初始化时机问题**: +- `HikariDataSource.getHikariPoolMXBean()` 方法在连接池尚未初始化时返回 `null` +- 定时任务在应用启动后立即执行,此时连接池可能还未完成初始化 +- 直接调用 `getActiveConnections()` 等方法会导致空指针异常 + +**相关代码**: +```java +// 问题代码 +@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) +public void monitorHikariPool() { + if (dataSource instanceof HikariDataSource) { + HikariDataSource hikariDataSource = (HikariDataSource) dataSource; + // 未检查 getHikariPoolMXBean() 返回值是否为 null + log.info("活跃连接数: {}", hikariDataSource.getHikariPoolMXBean().getActiveConnections()); + } +} +``` + +#### 解决方案 + +**修复后代码**: +```java +@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) +public void monitorHikariPool() { + if (dataSource instanceof HikariDataSource) { + HikariDataSource hikariDataSource = (HikariDataSource) dataSource; + HikariConfigMXBean config = hikariDataSource.getHikariConfigMXBean(); + var poolMXBean = hikariDataSource.getHikariPoolMXBean(); + + // 检查连接池是否已初始化 + if (poolMXBean == null) { + log.debug("HikariCP 连接池尚未初始化,跳过监控"); + return; + } + + log.info("=== HikariCP 连接池状态 ==="); + log.info("连接池名称: {}", config.getPoolName()); + log.info("活跃连接数: {}", poolMXBean.getActiveConnections()); + log.info("空闲连接数: {}", poolMXBean.getIdleConnections()); + log.info("等待获取连接的线程数: {}", poolMXBean.getThreadsAwaitingConnection()); + log.info("最大连接数: {}", config.getMaximumPoolSize()); + log.info("最小空闲连接数: {}", config.getMinimumIdle()); + } +} +``` + +**修复要点**: +1. 先获取 `HikariPoolMXBean` 实例并存储到变量 +2. 检查是否为 `null`,为 `null` 则跳过本次监控 +3. 使用变量访问连接池信息,避免重复调用 `getHikariPoolMXBean()` + +#### 修复文件 +- `fund-sys/src/main/java/com/fundplatform/sys/config/HikariMonitorConfig.java` + +#### 经验总结 +- **调用可能返回 null 的方法前必须做空值检查** +- **定时任务执行时需考虑资源初始化时机**,不能假设资源已就绪 +- **使用变量存储对象引用**,避免重复调用 getter 方法 + +--- + ## 预防措施清单 ### 前后端接口对接 @@ -624,6 +696,7 @@ curl http://localhost:8000/sys/api/v1/sys/health | TraceId 传递 | ContextInterceptor 必须提取并设置 TraceId | | **FeignClient 配置** | **有注册中心时必须移除 url 属性,仅保留 name** | | **Nacos 3.0 认证** | **客户端必须配置 username 和 password(默认都是 nacos)** | +| **定时任务资源检查** | **定时任务访问资源前需检查资源是否已初始化(如连接池)** | ### 功能开发流程 @@ -675,6 +748,7 @@ curl http://localhost:8000/sys/api/v1/sys/health | `TraceId 链路断裂` | ContextInterceptor 未提取 TraceId | 在 preHandle 中添加 TraceId 设置逻辑 | | `服务发现失效` | FeignClient 硬编码 URL | 移除 url 属性,仅保留 name 使用 Nacos 发现 | | `Nacos 注册失败 (认证错误)` | 缺少 username/password 配置 | 在 discovery 节点添加 username 和 password | +| `HikariPoolMXBean NullPointerException` | 定时任务执行时连接池未初始化 | 添加 poolMXBean 空值检查 | ---