同事碰到了一个问题,客户端和数据库服务端跨机房,防火墙将数据库连接断开了,客户端重连建立新连接,但是服务端没有清理老连接,导致连接池满。这个现象属于比较常见的一个场景。
尤其是生产环境可能设置严格的防火墙控制,对于数据库连接的检测和重连机制,就显得格外重要,一般是和连接池配置相关,无论用的什么连接池技术,Druid、Hikari…,相关的参数作用可以说大同小异,例如原始配置,
hikari:
maximum-pool-size:10 #最大连接数
max-lifetime:1800000 #连接最大存活时间
connection-test-query:select 1
仅设置了如下三个参数:
maximum-pool-size:10
max-lifetime:1800000
connection-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
的作用
定期检测空闲连接的有效性:HikariCP 会在后台线程中,每隔
keepalive-time
毫秒,对池中空闲超过该时间的连接执行
connection-test-query
。
自动清理失效连接:如果检测失败(如连接已断),该连接会被立即从池中移除,并触发创建新连接(保持池大小)。
防止僵尸连接堆积:即使防火墙静默断开连接,池也能在 30 秒内发现并清理,确保连接池始终包含有效连接。
其它参数的辅助作用
idle-timeout
:将空闲超过 5 分钟的连接回收(但若连接已断,
keepalive-time
会更早发现并清理)。
connection-timeout
:避免获取连接时无限等待,提升失败反馈速度。
leak-detection-threshold
:主要用于检测代码中连接未归还的泄漏问题,对防火墙断连导致的连接失效问题影响较小。
minimum-idle
:保持至少 5 个空闲连接,配合
keepalive-time
确保池中总有可用连接。
综上,keepalive-time 通过主动、定期验证空闲连接的有效性,及时剔除因防火墙断连而失效的连接,是解决”连接池满且不释放”问题的关键参数。
当然,其它参数(如
idle-timeout
、
connection-timeout
)有各自的作用,提升了整体的连接管理健壮性,但如果没有
keepalive-time
,池中仍可能长期堆积无效连接。
声明:来自bisal的个人杂货铺,仅代表创作者观点。链接:https://eyangzhen.com/7114.html