数据库连接池耗尽问题解决
问题现象
在模型推理服务运行过程中,发现数据库连接频繁报错:java.sql.SQLException: Connection pool is exhausted。通过Prometheus监控发现,数据库连接数持续接近最大连接数阈值(max_connections=200),而活跃连接数长时间维持在180以上。
根本原因分析
通过JVM堆栈分析工具定位到问题代码:
public class ModelInferenceService {
@Autowired
private DataSource dataSource;
public ModelResult predict(ModelInput input) throws SQLException {
// 问题代码段
Connection conn = dataSource.getConnection(); // 连接未正确关闭
try {
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM model_config WHERE id = ?");
stmt.setString(1, input.getModelId());
ResultSet rs = stmt.executeQuery();
// 处理结果...
} finally {
// 缺少conn.close()调用
}
}
}
解决方案与监控配置
1. 代码修复:使用try-with-resources确保连接自动关闭
public ModelResult predict(ModelInput input) throws SQLException {
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM model_config WHERE id = ?")) {
stmt.setString(1, input.getModelId());
ResultSet rs = stmt.executeQuery();
// 处理结果...
} // 自动关闭连接
}
2. 监控指标配置:在Prometheus中添加以下监控项
mysql_connections_active{instance="model-service"}:活跃连接数mysql_connections_max{instance="model-service"}:最大连接数mysql_connection_pool_wait_time_seconds:连接等待时间
3. 告警配置:在Grafana中设置以下告警规则
# 告警条件:活跃连接数超过最大连接数的80%
ALERT DatabaseConnectionExhausted
IF rate(mysql_connections_active[5m]) > 0.8 * mysql_connections_max
FOR 2m
ANNOTATIONS {
summary = "数据库连接池耗尽风险"
description = "活跃连接数{{ $value }}超过最大连接数的80%"
}
4. 连接池优化:调整HikariCP配置
spring:
datasource:
hikari:
maximum-pool-size: 50
minimum-idle: 10
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
通过以上配置,数据库连接池使用率从95%降低至75%,服务稳定性显著提升。

讨论