如何正确处理Node.js中的ECONNRESET错误?已修复PROTOCOL_CONNECTION_LOST
问题分析与解决方案
为什么ECONNRESET错误没被解决?
你的错误处理逻辑里虽然捕获了ECONNRESET并调用handleDisconnect,但大概率是handleDisconnect的实现存在缺陷:
- 没有彻底清理旧连接的残留资源(比如未完成的查询、绑定的事件)
- 重建连接后,未重新绑定所有必要的事件监听
- 连接断开重建期间,定时器仍在执行,导致多次触发错误或连接冲突
优化方案
1. 放弃单连接,改用MySQL连接池
单长连接极易因MySQL端超时、网络波动等原因断开,连接池会自动管理连接的创建、复用与销毁,遇到失效连接会自动重建,是更稳定的方案。示例代码:
const mysql = require('mysql2/promise'); // 创建连接池 const pool = mysql.createPool({ host: '你的数据库地址', user: '用户名', password: '密码', database: '数据库名', connectionLimit: 5, // 根据业务量调整连接数 waitForConnections: true }); // 封装插入函数 async function insertData(generatedValue) { let conn; try { conn = await pool.getConnection(); await conn.execute('INSERT INTO 表名 (字段名) VALUES (?)', [generatedValue]); } catch (err) { console.error('插入失败:', err); // 连接类错误由连接池自动处理,无需手动重建 if ([ 'ECONNRESET', 'PROTOCOL_CONNECTION_LOST' ].includes(err.code)) { console.log('连接异常,连接池将自动重建'); } } finally { if (conn) conn.release(); // 释放连接回池 } } // 定时器逻辑 setInterval(async () => { try { const value = Math.random(); // 替换成你的值生成逻辑 await insertData(value); // WebSocket推送逻辑... } catch (wsErr) { console.error('推送失败:', wsErr); } }, 1000);
2. 捕获定时器中的所有异步错误
setInterval的异步回调如果抛出未捕获错误,会直接导致进程崩溃。必须在回调内部添加try-catch,避免未处理的异常扩散。
3. 检查MySQL服务器超时配置
查看MySQL的wait_timeout和interactive_timeout参数,这两个参数控制连接的空闲超时时间,若值过短,MySQL会主动断开空闲连接。可通过以下SQL查询:
SHOW VARIABLES LIKE '%timeout';
如需调整,可在MySQL配置文件中修改(比如设置为20小时):
wait_timeout = 72000 interactive_timeout = 72000
注意:这只是辅助手段,核心解决方案还是使用连接池。
4. 完善handleDisconnect(若坚持用单连接)
如果一定要用单连接,需确保handleDisconnect能彻底重建连接并恢复业务逻辑:
function handleDisconnect() { // 销毁旧连接 if (connection) { connection.destroy(); } // 重新创建连接 connection = mysql.createConnection({ /* 你的连接配置 */ }); connection.connect(err => { if (err) { console.error('重连失败,1秒后重试:', err); setTimeout(handleDisconnect, 1000); return; } console.log('数据库重连成功'); // 重新绑定错误事件 connection.on('error', function(err) { console.log('db error', err); if(err.code === 'PROTOCOL_CONNECTION_LOST' || err.code === 'ECONNRESET') { handleDisconnect(); } else { throw err; } }); }); }
注意:这种方式下,重连期间的数据库操作会失败,需额外添加重试逻辑,否则会丢失数据。
内容的提问来源于stack exchange,提问作者Emmatech
相关产品推荐
相关产品推荐

