同事碰到了一个问题,客户端和数据库服务端跨机房,防火墙将数据库连接断开了,客户端重连建立新连接,但是服务端没有清理老连接,导致连接池满。这个现象属于比较常见的一个场景。
尤其是生产环境可能设置严格的防火墙控制,对于数据库连接的检测和重连机制,就显得格外重要,一般是和连接池配置相关,无论用的什么连接池技术,Druid、Hikari...,相关的参数作用可以说大同小异,例如原始配置,
hikari:
maximum-pool-size:10 #最大连接数
max-lifetime:1800000 #连接最大存活时间
connection-test-query:select 1maximum-pool-size:10max-lifetime:1800000connection-test-query:select 1此时连接池的行为是:
testOnBorrow,但未显式配置,HikariCP 默认仅在连接创建、借出或归还时有限验证)才会执行 connection-test-query。如果连接在池中空闲时已被防火墙断开,连接池并不知道,仍然认为这些连接可用。max-lifetime:即使连接已失效,也要等 30 分钟(1800000ms)后才会被强制移除。在此期间,10 个连接可能全部变成"僵尸连接",新的请求无法从池中获取有效连接,导致连接池"满"但实际不可用。因此,需要增加一些参数配置,
hikari:
maximum-p0ol-size:10 #根据实际业务需求调整
minimum-idle: 5
idle-timeout: 300000
max-lifetime: 1800000
connection-timeout: 30000
keepalive-time: 30000
leak-detection-threshold: 180000
connection-test-query: select 1新增加了这几个:
keepalive-time: 30000 # 30秒
idle-timeout: 300000 # 5分钟
connection-timeout: 30000 # 30秒
leak-detection-threshold: 180000 # 3分钟
minimum-idle: 5其中 keepalive-time 是最直接解决防火墙断连问题的参数。
keepalive-time 的作用keepalive-time 毫秒,对池中空闲超过该时间的连接执行 connection-test-query。idle-timeout:将空闲超过 5 分钟的连接回收(但若连接已断,keepalive-time 会更早发现并清理)。connection-timeout:避免获取连接时无限等待,提升失败反馈速度。leak-detection-threshold:主要用于检测代码中连接未归还的泄漏问题,对防火墙断连导致的连接失效问题影响较小。minimum-idle:保持至少 5 个空闲连接,配合 keepalive-time 确保池中总有可用连接。综上,keepalive-time 通过主动、定期验证空闲连接的有效性,及时剔除因防火墙断连而失效的连接,是解决"连接池满且不释放"问题的关键参数。
当然,其它参数(如 idle-timeout、connection-timeout)有各自的作用,提升了整体的连接管理健壮性,但如果没有 keepalive-time,池中仍可能长期堆积无效连接。