连接池是后端系统中最容易被忽视的性能瓶颈之一。很多团队直接用 Spring Boot 默认参数上线,结果在流量高峰期出现连接超时、线程阻塞等问题。
这篇文章记录我最近一次连接池调优的过程,从发现问题到最终配置,附带实际压测数据。
为什么要调连接池
Spring Boot 2.x 开始默认使用 HikariCP,它的默认配置在低并发场景下完全够用。但当 QPS 上来后,默认的 maximumPoolSize=10 很快就会成为瓶颈。
一个典型的症状是:请求量增长后,接口响应时间突然从几十毫秒变成几百毫秒甚至几秒——不是因为 SQL 变慢了,而是线程在等连接。
核心参数
HikariCP 有几个关键参数需要理解:
maximumPoolSize — 连接池最大连接数。默认 10,生产环境建议从 CPU 核数 * 2 + 1 起步,根据实际负载调整。
minimumIdle — 连接池最小空闲连接数。默认等于 maximumPoolSize,意味着启动时就创建满连接。如果不需要预热,可以设小一些。
connectionTimeout — 等待连接的最大时间(毫秒)。默认 30 秒太长,建议设 3-5 秒,让请求快速失败而不是长时间阻塞。
idleTimeout — 空闲连接最大存活时间。默认 10 分钟,建议保持或适当缩短。
maxLifetime — 连接最大存活时间。默认 30 分钟,应该比数据库的连接超时时间短一些。
leakDetectionThreshold — 连接泄漏检测阈值。开发环境建议设 10 秒,生产环境建议设为 0(关闭),避免额外开销。
一个真实案例
我们有个服务使用默认配置上线,maximumPoolSize=10。起初每天几十万请求没什么问题。后来业务量增长到近百万 QPS,监控显示:
- 数据库连接数恒定在 10 个
- 接口 P99 延迟从 50ms 飙升到 2s+
- HikariCP 日志中大量
Connection is not available告警
分析后发现,每个请求平均需要 15ms 的数据库操作时间。10 个连接理论上每秒能处理 1000ms / 15ms * 10 ≈ 666 个请求。但实际中还有网络延迟、事务等待等因素。
调整后的配置:
spring:
datasource:
hikari:
maximum-pool-size: 30
minimum-idle: 10
connection-timeout: 5000
idle-timeout: 600000
max-lifetime: 1800000
leak-detection-threshold: 0
调整后 P99 延迟降到 200ms 以内,接口成功率恢复到 99.99%。
如何确定合适的连接数
一个简单的公式:
连接数 ≈ (QPS × 平均查询时间) + 缓冲
比如 QPS 1000,平均查询 20ms:
连接数 = (1000 × 0.02) + 缓冲 = 20 + 5~10 = 25~30
但这只是理论值。实际中还要考虑:
- 数据库服务器的
max_connections限制 - 如果有多个服务实例共享同一个数据库,需要分摊连接数
- 事务中持有连接的时间
不要过度调大
连接数不是越大越好。每个连接都占用数据库内存和 CPU 资源。MySQL 默认 max_connections=151,如果 5 个实例各开 50 个连接,已经超出限制。
一般来说:
- 连接数 < 50 适合大多数场景
- 50~100 需要确认数据库能承受
- 100+ 通常说明架构有问题,考虑引入缓存或读写分离
总结
连接池调优的要点:
- 先理解默认参数的含义再动手
- 要有监控数据做依据,别凭感觉调
connectionTimeout设短一点,让系统快速失败- 连接数和数据库容量匹配
- 调完后一定要压测验证
调连接池是最简单、回报最高的性能优化之一。花半小时调参,可能省下几天排查问题的功夫。
评论
评论已关闭。