Spring Boot高CPU时无法获取JDBC连接问题排查求助
问题排查与解决方案
核心问题根源
1. 无连接池导致的连接创建开销与资源耗尽
你当前使用的DriverManagerDataSource并非连接池实现,它会为每个数据库请求新建一个JDBC连接。当EC2 CPU利用率过高(80%+)时,系统资源(CPU、网络IO)紧张,新建连接的TCP握手、数据库认证等操作耗时大幅增加,同时并发请求堆积会导致短时间内创建大量连接,直接打满MySQL的max_connections(MySQL 5.7默认值为151),最终触发无法获取连接的错误。
2. CPU高负载的连锁反应
CPU利用率过高时,不仅连接创建过程变慢,应用线程也可能因资源争抢出现阻塞,导致Hibernate/JPA获取连接的超时时间被触发,抛出Unable to acquire JDBC Connection异常。
针对性解决方案
1. 替换为连接池(优先推荐)
使用Spring Boot默认的高性能连接池HikariCP,它会复用连接、控制连接数、自动管理连接生命周期,彻底解决无连接池带来的问题。修改数据源配置代码如下:
@Bean(name = "datasource") @Primary public DataSource getDataSourceFactory() { HikariDataSource hikariDataSource = new HikariDataSource(); hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); hikariDataSource.setUsername(System.getenv("USER")); hikariDataSource.setPassword(System.getenv("PASSWORD")); hikariDataSource.setJdbcUrl(System.getenv("URL")); // 核心连接池配置,可根据业务调整 hikariDataSource.setMaximumPoolSize(20); // 最大连接数,建议小于MySQL的max_connections hikariDataSource.setConnectionTimeout(30000); // 获取连接超时时间(毫秒) hikariDataSource.setIdleTimeout(300000); // 连接空闲超时时间(毫秒) hikariDataSource.setMaxLifetime(1800000); // 连接最大存活时间(毫秒) return hikariDataSource; }
同时确保Spring Boot依赖中包含HikariCP(Spring Boot 2.x及以上默认已引入)。
2. 调整MySQL参数
- 修改
max_connections:根据业务并发量适当调大该值(例如设为500),但需注意服务器内存容量(每个MySQL连接约占用1MB左右内存)。修改后重启MySQL生效:
并在SET GLOBAL max_connections = 500;my.cnf中配置永久生效:[mysqld] max_connections = 500 - 保持
wait_timeout和interactive_timeout为60分钟即可,当前场景下这两个参数不是核心问题。
3. 排查并解决CPU高负载的根源
CPU利用率过高是触发问题的诱因,需进一步排查:
- 用
top、htop工具定位占用CPU的进程/线程,结合jstack分析应用线程是否存在阻塞、死循环等情况; - 开启MySQL慢查询日志,定位耗时较长的SQL语句,优化查询逻辑、添加索引;
- 检查应用是否存在内存泄漏,导致频繁GC占用CPU(可通过
jstat、VisualVM等工具分析)。
关于JDBC连接器的最大连接数限制
JDBC驱动本身没有硬编码的最大连接数限制,但存在以下层面的限制:
- MySQL服务器限制:由
max_connections参数控制,默认151,超过该值后无法创建新连接; - 操作系统限制:每个数据库连接对应一个文件句柄,操作系统的
open files限制(可通过ulimit -n查看)会限制最大连接数,若该值过小,需调整系统配置; - 应用并发限制:无连接池时,应用的并发请求数直接对应数据库连接数,高并发下极易触发上述限制。
内容的提问来源于stack exchange,提问作者Swagat
相关产品推荐
相关产品推荐

