如何在node-postgres(pg)npm包中动态检测PostgreSQL连接断开
pg连接池实现断开连接监听的方案
pg(node-postgres)的连接池没有原生提供disconnect事件,你可以通过以下几种方式实现断开状态的动态检测:
方案1:监听连接池内置的remove事件
连接池在任意连接被销毁移除时会触发remove事件,触发场景覆盖:连接异常断开被池清理、空闲连接超时回收、手动调用pool.end()关闭池连接,回调参数为被移除的数据库客户端实例,可直接替代你预期的disconnect事件逻辑:
pool.on('remove', (client) => { console.error('<------------------------disconnected------------------------>') // 可在此处添加断开后的告警、计数、重连触发逻辑 })
如果需要区分「异常断开」和「正常回收连接」,可以配合客户端实例的错误标记做判断。
方案2:在连接创建时给单个客户端绑定断开事件
连接池的connect事件会返回新创建的客户端实例,你可以直接给每个客户端实例绑定连接层面的error和end事件,精准捕获单条连接的状态变化:
pool.on('connect', (client) => { console.error('<------------------------connected------------------------>') // 捕获连接异常(比如网络中断、数据库主动踢除连接、服务重启) client.on('error', (err) => { console.error('connection error:', err.message) }) // 连接socket完全关闭时触发,不管是正常断开还是异常断开 client.on('end', () => { console.error('<------------------------disconnected------------------------>') }) })
补充:兜底健康检测逻辑
部分特殊网络场景(比如防火墙静默丢包、TCP半连接)下,socket不会主动触发end/error事件,会导致事件监听漏判,建议配合定时健康检查做兜底:
// 每30秒执行一次连接可用性检测 setInterval(async () => { let healthClient = null try { healthClient = await pool.connect() await healthClient.query('SELECT 1') healthClient.release() // 连接状态正常 } catch (err) { console.error('<------------------------connection unavailable------------------------>', err.message) // 此处可触发重连、服务降级逻辑 } }, 30000)
注意事项
- 不要直接绑定不存在的
disconnect事件,连接池不会触发该事件,绑定后逻辑不会执行 remove事件触发时,对应客户端已经从连接池中移除,不需要手动调用release释放- 健康检查的间隔可以根据业务对连接可用性的敏感度调整,一般10s~60s都是合理区间
内容的提问来源于stack exchange,提问作者Koperumsozhan VR
相关产品推荐
相关产品推荐

