docs: 添加问题10 HikariMonitorConfig空指针异常到问题清单

This commit is contained in:
zhangjf 2026-02-19 18:26:28 +08:00
parent 39db7c8b7a
commit d11ed1ba1e

View File

@ -19,6 +19,7 @@
| 7 | 全链路追踪 | TraceContextHolder未在HTTP入口初始化导致链路断裂 | 高 | 已解决 | | 7 | 全链路追踪 | TraceContextHolder未在HTTP入口初始化导致链路断裂 | 高 | 已解决 |
| 8 | OpenFeign配置 | FeignClient硬编码URL导致Nacos服务发现失效 | 高 | 已解决 | | 8 | OpenFeign配置 | FeignClient硬编码URL导致Nacos服务发现失效 | 高 | 已解决 |
| 9 | Nacos 配置 | Nacos 3.0 客户端缺少 username/password 认证配置 | 高 | 已解决 | | 9 | Nacos 配置 | Nacos 3.0 客户端缺少 username/password 认证配置 | 高 | 已解决 |
| 10 | 连接池监控 | HikariMonitorConfig空指针异常 | 中 | 已解决 |
--- ---
@ -594,6 +595,77 @@ curl http://localhost:8000/sys/api/v1/sys/health
--- ---
### 问题 10HikariMonitorConfig 空指针异常
#### 问题现象
服务启动后,定时任务日志中持续报错:
```
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 | | TraceId 传递 | ContextInterceptor 必须提取并设置 TraceId |
| **FeignClient 配置** | **有注册中心时必须移除 url 属性,仅保留 name** | | **FeignClient 配置** | **有注册中心时必须移除 url 属性,仅保留 name** |
| **Nacos 3.0 认证** | **客户端必须配置 username 和 password默认都是 nacos** | | **Nacos 3.0 认证** | **客户端必须配置 username 和 password默认都是 nacos** |
| **定时任务资源检查** | **定时任务访问资源前需检查资源是否已初始化(如连接池)** |
### 功能开发流程 ### 功能开发流程
@ -675,6 +748,7 @@ curl http://localhost:8000/sys/api/v1/sys/health
| `TraceId 链路断裂` | ContextInterceptor 未提取 TraceId | 在 preHandle 中添加 TraceId 设置逻辑 | | `TraceId 链路断裂` | ContextInterceptor 未提取 TraceId | 在 preHandle 中添加 TraceId 设置逻辑 |
| `服务发现失效` | FeignClient 硬编码 URL | 移除 url 属性,仅保留 name 使用 Nacos 发现 | | `服务发现失效` | FeignClient 硬编码 URL | 移除 url 属性,仅保留 name 使用 Nacos 发现 |
| `Nacos 注册失败 (认证错误)` | 缺少 username/password 配置 | 在 discovery 节点添加 username 和 password | | `Nacos 注册失败 (认证错误)` | 缺少 username/password 配置 | 在 discovery 节点添加 username 和 password |
| `HikariPoolMXBean NullPointerException` | 定时任务执行时连接池未初始化 | 添加 poolMXBean 空值检查 |
--- ---