HikariCP连接池耗尽:全站接口超时的根因与解决
·
HikariCP 连接池耗尽:全站接口超时的根因与解决
一个慢接口占着数据库连接不释放,连接池很快被耗尽,其他接口拿不到连接,全站跟着集体超时。本文通过一个「报表慢 SQL 拖垮全站」的真实案例,讲清楚连接池耗尽的根因(慢 SQL 霸占连接),给出 HikariCP 参数配置方法,以及「快速失败 > 无限等待」的应对思路。
一、问题案例
一个报表接口,SQL 写得糙,高峰期要跑 30 秒。平时调用不多,一直没当回事。
直到某天运营在高峰期批量导出报表,几十个请求同时打过来。几分钟后,全站所有接口集体超时——不光是报表,登录、下单、查订单全挂了。
看数据库:CPU 并不高,连接数却打满了。看应用日志,全是同一类报错:
HikariPool-1 - Connection is not available, request timed out after 30000ms
二、原理详解:连接是稀缺资源,慢 SQL 是元凶
数据库连接池里就那么多连接(HikariCP 默认 maximumPoolSize=10),一个连接同一时刻只能服务一个请求。慢 SQL 占着连接不释放,等于把公共资源霸占了:
慢 SQL(30秒)× 并发几十个 → 10 个连接全被占满
↓
其他接口排队等连接 → 等满 connectionTimeout → 集体超时
连接池打满只是表象,真正的病根是慢 SQL。 不治慢 SQL,光加大连接池,只是把问题往后拖——连接再多,慢 SQL 一多照样打满,还会把数据库压垮。
三、实战代码:治本 + 合理配置
第一步(治本):修慢 SQL。
给报表 SQL 加索引、拆分批、或者改成异步生成。慢 SQL 从 30 秒降到 1 秒以内,连接占用时间短了,池子自然周转得过来。
第二步:合理配置 HikariCP。
spring:
datasource:
hikari:
maximum-pool-size: 20 # 最大连接数,按公式估,别拍脑袋
connection-timeout: 5000 # 拿不到连接 5 秒就失败,别让请求干等 30 秒
max-lifetime: 1800000 # 连接最大存活 30 分钟,防止被数据库端断开
- maximum-pool-size:经验公式
连接数 ≈ (CPU 核数 × 2) + 磁盘数。2 核 4G 的机器,20 个左右就够; - connection-timeout:调小一点,拿不到连接快速失败,比排队 30 秒再超时好——至少不会拖垮其他接口;
- max-lifetime:设成比数据库的连接超时短一点,避免连接被数据库断开后应用还在用。
四、延伸:快速失败 > 无限等待
连接池耗尽的应对思路,不是「把超时调大让请求继续等」,恰恰相反——让拿不到连接的请求快速失败,配合限流和降级:
- 报表这种重接口,加限流(同时只允许几个请求);
- 或者改异步(提交任务后立即返回,后台慢慢跑);
- 前台接口拿不到连接就快速报错,别把全站都拖下水。
五、总结 + 避坑建议
- 连接池打满,先查慢 SQL,那是病根,加连接数是治标。
- 连接数按公式估:
(核数×2)+磁盘数,别无脑调大。 connection-timeout调小,拿不到连接快速失败,别让请求干等。- 重接口配限流或异步,别让它霸占连接池。
我是无羡(小剑),全栈偏后端的独立开发者。
作品集:无羡 · 独立开发者作品集
如果对你有帮助,欢迎点赞、收藏、关注。
更多推荐



所有评论(0)