面试题答案
一键面试错误监测
- 语法错误:在Node.js中,语法错误在代码解析阶段就会抛出,无法在运行时捕获。为了避免因语法错误导致进程崩溃,可在启动工作进程前进行代码语法检查。例如,使用
eslint
等工具对代码进行静态分析,确保代码语法正确。 - 运行时错误:在工作进程中,可以使用
process.on('uncaughtException', callback)
和process.on('unhandledRejection', callback)
来捕获未处理的异常和未处理的Promise拒绝。
错误传递
- 使用进程间通信(IPC):工作进程捕获到错误后,可以通过
process.send(message)
方法将错误信息发送给主进程。主进程通过监听message
事件来接收工作进程发送的错误信息。
错误处理
- 主进程处理:主进程接收到错误信息后,可以根据具体情况采取不同的处理策略。例如,记录错误日志,重启出现错误的工作进程等。
- 重启工作进程:主进程可以使用
cluster.fork()
方法重启出现错误的工作进程。同时,为了避免频繁重启导致系统资源耗尽,可以设置一定的重启策略,如在短时间内多次重启失败后暂停重启等。
相关模块和方法
- cluster模块:用于创建和管理Node.js集群。
cluster.fork()
方法用于创建新的工作进程,cluster.on('exit', callback)
事件用于监听工作进程的退出事件。 - process模块:
process.on('uncaughtException', callback)
用于捕获未处理的异常,process.on('unhandledRejection', callback)
用于捕获未处理的Promise拒绝,process.send(message)
用于向父进程发送消息。
代码架构示例
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// 主进程
console.log(`主进程 ${process.pid} 正在运行`);
// 监听工作进程退出事件
cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
// 重启工作进程
cluster.fork();
});
// 监听工作进程发送的错误信息
process.on('message', (msg) => {
if (msg.error) {
console.error('工作进程出现错误:', msg.error);
}
});
// 创建工作进程
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
// 工作进程
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end('你好,世界!\n');
});
server.listen(8000, () => {
console.log(`工作进程 ${process.pid} 正在监听8000端口`);
});
// 捕获未处理的异常
process.on('uncaughtException', (err) => {
console.error('未处理的异常:', err);
process.send({ error: err.message });
// 退出工作进程
process.exit(1);
});
// 捕获未处理的Promise拒绝
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason, 'Promise:', promise);
process.send({ error: reason.message });
// 退出工作进程
process.exit(1);
});
}
上述代码展示了如何在Node.js集群架构下,统一捕获和处理工作进程中的错误。主进程负责监听工作进程的退出事件和接收错误信息,并根据情况重启工作进程。工作进程则通过捕获未处理的异常和未处理的Promise拒绝,并将错误信息发送给主进程,避免单个进程的错误导致整个集群崩溃。