fix(db): 修复数据库断连后无法自动恢复的问题

- 添加连接超时配置防止无限等待
- 捕获连接池错误避免进程崩溃
- 缩短心跳检测间隔至5秒
This commit is contained in:
2026-02-27 08:56:19 +08:00
parent e44cf10a82
commit 58c3880732
3 changed files with 38 additions and 2 deletions

View File

@@ -0,0 +1,29 @@
# 事故报告:数据库断电后服务无法自动恢复
日期2026-02-10
## 1. 问题描述
用户反馈 PostgreSQL 数据库因断电突然离线,恢复后 `Web_BLS_Heartbeat_Server` 服务没有自动重连并恢复写入,处于"毫无反应"的状态。
## 2. 原因分析
经过代码审查,发现以下潜在原因:
1. **连接超时缺失**`pg` 连接池默认配置中 `connectionTimeoutMillis` 未设置默认为0即无限等待。当数据库主机突然断电非正常关闭 TCP 连接)时,客户端 Socket 可能处于半打开状态,导致 `pool.connect()``pool.query()` 无限挂起,既不成功也不报错。
2. **重试间隔过长**:原有的 `HeartbeatProcessor` 离线检测机制设定为 60 秒检查一次,对于需要快速恢复的场景响应过慢。
3. **未捕获的 Pool 错误**`DatabaseManager` 未监听 `pool.on('error')`,虽然这通常导致进程崩溃而非挂起,但也属于稳定性隐患。
## 3. 修复措施
### 3.1 DatabaseManager (`src/db/databaseManager.js`)
- **新增配置**:添加 `connectionTimeoutMillis: 5000`。这强制任何获取连接的操作在 5 秒内必须完成,否则抛出 `ETIMEDOUT` 错误。这确保了应用层能感知到“网络不通”,而不是无限等待。
- **错误监听**:添加 `pool.on('error')` 处理程序,防止后台连接断开导致 Node.js 进程意外退出。
### 3.2 HeartbeatProcessor (`src/processor/heartbeatProcessor.js`)
- **缩短检测间隔**:将数据库离线后的健康检查间隔从 60 秒缩短为 5 秒。这意味着数据库恢复后,服务最快在 5 秒内即可恢复消费。
## 4. 验证结果
编写了模拟测试脚本 `scripts/test_reconnect_logic.js` 进行验证:
1. **模拟断连**:模拟 DB 抛出 `ETIMEDOUT` 错误。
- 结果Consumer 成功暂停,进入离线模式。
2. **模拟恢复**5秒后模拟 DB 连接恢复。
- 结果Consumer 自动恢复Resume积压的数据成功写入。
## 5. 结论
系统现在具备了对数据库“突然断电/断网”场景的自动感知与快速恢复能力。