Boot 里 HikariCP 的默认值是多少?池耗尽的时候应用表现成什么?连接泄漏怎么查?池该设多大?这篇在 Spring Boot 4.0.8、HikariCP、MySQL 上逐项实测。
(Boot 创建的 HikariDataSource 是惰性的:第一次取连接时才真正建池;下面先 select 1 触发它) DataSource 的类型:com.zaxxer.hikari.HikariDataSource poolName=HikariPool-1,maximumPoolSize=10,minimumIdle=10,connectionTimeout=30000 ms,idleTimeout=600000 ms,maxLifetime=1800000 ms keepaliveTime=120000,validationTimeout=5000 ms,leakDetectionThreshold=0,autoCommit=true,connectionTestQuery=null,initializationFailTimeout=1 启动后 1.5 秒:total=10,active=0,idle=10,waiting=0 MySQL 服务端 show processlist 里属于本程序的连接数:10
最大 10、最小空闲 10(固定大小),连接超时 30 秒,最大寿命 30 分钟;启动后立刻建好 10 个连接。
池大小 2,两个连接都被占住:total=2,active=2,idle=0 第 3 个请求等了 1008 ms 之后失败:CannotGetJdbcConnectionException / 最里面:SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 1005ms (total=2, active=2, idle=0, waiting=0) 两个连接放回之后再请求:1,用时 3 ms 池大小 2、connection-timeout=3000 ms,两个连接各被占 600 ms:第 3 个请求 结果=1,等了 603 ms
等满 connection-timeout 抛 CannotGetJdbcConnectionException;没超时就是一次慢请求。
leak-detection-threshold=500:LOG WARN c.zaxxer.hikari.HikariConfig - HikariPool-1 - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.
故意不关连接,持有了 2600 ms(leak-detection-threshold=2000 ms)
日志里和泄漏有关的行:4
LOG WARN c.z.hikari.pool.ProxyLeakTask - Connection leak detection triggered for com.mysql.cj.jdbc.ConnectionImpl@50756c76 on thread main, stack trace follows
java.lang.Exception: Apparent connection leak detected
堆栈里指向我这段代码的帧:at demo.Main.main(Main.java:33)leak-detection-threshold 不能小于 2000 ms;触发时打印持有者的堆栈。
maximum-pool-size=2:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 366 次,即 92 次/秒 maximum-pool-size=4:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 702 次,即 176 次/秒 maximum-pool-size=10:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 1650 次,即 413 次/秒 maximum-pool-size=32:32 个客户端线程各自循环执行 select sleep(0.02)(约 20 ms),4 秒内完成 4746 次,即 1187 次/秒
池大小决定到数据库的并发度,理想情况下吞吐随池大小线性增长。