虽然可以通过 require('domain') 配置,但 Node.js 官方已明确废弃该模块,生产环境建议改用 process.on 监听全局异常。本文先展示旧版配置方法以供维护参考,再提供现代最佳实践。
核心结论:domain 模块自 Node.js v4.0.0 起已标记为废弃,新代码不应依赖该机制捕获异常。
- 适用场景:仅用于理解或维护无法立即重构的旧代码。
- 迁移准备:评估将 domain 逻辑迁移到 process.on 和 Promise catch 的工作量。
- 验收标准:确认全局异常监听器能捕获错误且进程不会静默退出。
Domain 模块状态与遗留配置参考
对于仍需维护旧系统的开发者,了解 domain 的历史配置方式有助于代码迁移。以下是典型的 domain 异常捕获写法,请勿在新项目中使用:
const domain = require('domain');
const http = require('http');
const d = domain.create();
d.on('error', (err) => {
console.error('Domain 捕获错误:', err);
// 旧式处理:尝试恢复或关闭服务器
d.dispose();
});
d.run(() => {
http.createServer((req, res) => {
// 业务逻辑在此作用域内
throw new Error('Domain 内异常');
}).listen(3000);
});这种模式试图将多个 I/O 操作分组以便统一处理错误,但实际会导致上下文混淆和性能开销,因此官方已停止维护。
现代标准:process.on 全局异常监听
现代 Node.js 应用捕获未捕获异常的标准代码模式,可直接替换原有的 domain 逻辑。请将以下代码放入应用入口文件(如 app.js 或 index.js)的最顶部:
process.on('uncaughtException', (err) => {
console.error('未捕获异常:', err);
// 记录日志后优雅退出,避免状态不一致
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
// 可选:记录堆栈后退出
// process.exit(1);
});确保在任何业务逻辑加载前注册,以便捕获启动阶段的错误。
代码逻辑对比:Domain vs Process.on
为了更清晰地理解迁移路径,以下是两种机制的核心逻辑对比:
- 作用域:domain 基于隐式上下文绑定,容易污染作用域;process.on 基于全局事件,边界清晰。
- 异步支持:domain 无法可靠处理所有异步场景(如定时器、回调);process.on 作为最后防线捕获所有进程级异常。
- 维护成本:domain 需要手动创建、绑定和释放;process.on 只需注册一次,配合局部 try/catch 使用。
建议优先使用 async/await 配合 try/catch 处理业务逻辑错误,将 process.on 仅作为兜底策略。
验证步骤与排查方法
配置完成后,需通过以下步骤验证异常处理机制是否生效:
1. 故意抛出错误
在代码中添加测试用例,模拟同步和异步错误:
// 同步错误测试
throw new Error('Sync Error Test');
// 异步错误测试
setTimeout(() => {
throw new Error('Async Error Test');
}, 100);2. 观察控制台输出
运行 node app.js,确认看到“未捕获异常”日志输出,且进程正常退出(退出码为 1)。
3. 检查日志文件
确认错误堆栈被完整记录到日志系统中,便于后续排查。若使用 PM2,可通过 pm2 logs 查看。
4. 验证重启机制
若配置了进程管理器,确认进程退出后能自动重启新实例,避免服务中断。
常见坑与风险提示
1. 不要试图复活 domain:网上部分旧教程仍推荐使用 domain,这在当前 Node.js 版本中属于过时实践,可能带来隐蔽 Bug。
2. 避免吞掉错误:在 uncaughtException 监听器中不要只打印日志而不退出进程,否则应用可能处于不一致状态,导致数据损坏。
3. 异步边界清晰:使用 async/await 时,务必在外层包裹 try/catch,不要完全依赖全局监听,全局监听仅用于兜底。
4. 性能影响:频繁的全局异常捕获可能影响性能,应将其作为最后防线而非主要控制流。
参考来源
- Node.js 官方文档 - Domain 模块状态说明,页面标题:Domain,URL:https://nodejs.org/api/domain.html
- Node.js 官方文档 - Process 事件,页面标题:Process,URL:https://nodejs.org/api/process.html