面试题答案
一键面试创建子进程
- 引入模块:在 Node.js 项目中,首先引入
cluster
和http
模块。const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length;
- 主进程逻辑:在主进程中,通过
cluster.fork()
方法创建子进程。一般会根据 CPU 核心数来创建相应数量的子进程。if (cluster.isMaster) { console.log(`主进程 ${process.pid} 正在运行`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`工作进程 ${worker.process.pid} 已退出`); cluster.fork(); }); }
- 子进程逻辑:在子进程(
cluster.isWorker
)中,创建 HTTP 服务器来处理请求。else { const server = http.createServer((req, res) => { res.writeHead(200); res.end('你好,世界!'); }); server.listen(3000, () => { console.log(`工作进程 ${process.pid} 已启动,监听端口 3000`); }); }
分配请求
- 负载均衡策略:Node.js 的
cluster
模块内部使用了内置的负载均衡策略,基于 Round - Robin 算法。主进程接收所有的新连接,然后将这些连接循环分配给各个工作进程。 - 无需额外代码:对于基本的 HTTP 请求分配,开发者无需额外编写负载均衡分配代码,
cluster
模块会自动完成请求在子进程间的均衡分配。
处理子进程间的通信
- 发送消息:工作进程和主进程之间可以通过
worker.send(message)
和process.send(message)
方法来发送消息。例如,工作进程可以向主进程发送其当前的负载情况。// 工作进程发送消息 setInterval(() => { process.send({ type: 'load', value: getLoad() }); }, 1000);
- 接收消息:通过
cluster.on('message', (worker, message)
(主进程)和process.on('message', (message)
(工作进程)来接收消息。例如主进程接收工作进程发送的负载信息。// 主进程接收消息 cluster.on('message', (worker, message) => { if (message.type === 'load') { console.log(`工作进程 ${worker.process.pid} 的负载: ${message.value}`); } });
处理子进程间的错误
- 工作进程错误处理:在工作进程中,可以监听
uncaughtException
事件来处理未捕获的异常。当捕获到异常时,可以向主进程发送错误信息,然后安全地关闭自身。process.on('uncaughtException', (err) => { console.error('工作进程中发生未捕获异常:', err); process.send({ type: 'error', error: err.message }); process.exit(1); });
- 主进程错误处理:主进程通过监听
cluster
的exit
事件,当工作进程因为错误退出时,可以选择重新启动该工作进程。cluster.on('exit', (worker, code, signal) => { console.log(`工作进程 ${worker.process.pid} 已退出,原因: ${code || signal}`); cluster.fork(); });