使用集群构建具备崩溃容错的 Node.js 应用
Source: Dev.to
请提供您希望翻译的具体文本内容(文章正文),我将为您完整地翻译成简体中文,并保留原有的 Markdown 格式、代码块和技术术语。谢谢!
Source: …
内核
内核是操作系统(例如 Linux 内核)的核心组件。
它的工作是:
- 管理每个正在运行的程序
- 为每个程序分配独立的内存空间
- 将程序相互隔离
如果你在运行两个应用程序:
app1 | app2
内核会保持它们分离,使它们 不能相互破坏对方的内存。
如果 app2 崩溃,内核会确保它 在隔离状态下自行终止,并且不影响 app1。
这部分大多数人都了解。
大多数人忽略的部分
内核 不仅仅是杀死崩溃的应用,它还 向启动该应用的进程报告崩溃。
概念上看起来是这样:
int main() {
return 0; // 让事情崩溃,但不要让它们把所有东西都带走。
}
这就是为什么电话线路不会真的“挂断”。
这也是为什么浏览器感觉不可被杀死。
Node.js 也能做到
你可以在 Node.js 中使用 clusters 完全实现相同的功能。
- Clusters 不是 线程。
- 它们是 真实的操作系统进程。
当你 fork 一个 cluster 时,实际上是在当前实例之上启动 另一个 Node.js 实例。
我经常这样使用。例如,我的分析器在工作进程的 cluster 中接收实时事件,而 GUI 则在主进程中运行。如果某个工作进程崩溃,UI 仍然保持存活。

参考: How I Built a Graphics Renderer for Node.js
Node.js 中的集群
这里有一个简单示例:一个在集群中运行的服务器,随机崩溃并自动重启。
// cluster-demo.js
const cluster = require('cluster');
const os = require('os');
if (cluster.isPrimary) {
console.log(`primary ${process.pid} is running`);
const numCPUs = os.cpus().length;
// fork a couple of workers
for (let i = 0; i < Math.min(numCPUs, 2); i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died (code=${code}, signal=${signal})`);
setTimeout(() => {
console.log('Restarting worker...');
cluster.fork();
}, 1000);
});
cluster.on('online', (worker) => {
console.log(`Worker ${worker.process.pid} is online`);
});
} else {
console.log(`Worker ${process.pid} started`);
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end(`Hello from worker ${process.pid}`);
});
server.listen(3000, () => {
console.log(`Worker ${process.pid} listening on port 3000`);
});
// simulate random crashes
const crashTimeout = Math.floor(Math.random() * 30000) + 10000;
setTimeout(() => {
console.log(`Worker ${process.pid} will crash in 5 seconds...`);
setTimeout(() => {
throw new Error(`Simulated crash in worker ${process.pid}`);
}, 5000);
}, crashTimeout);
process.on('SIGTERM', () => {
console.log(`Worker ${process.pid} shutting down gracefully`);
server.close(() => process.exit(0));
});
}
else 块内部的所有代码都在 专用的集群进程 中运行。
在本例中我们启动了两个工作进程(或最多两个,取决于 CPU 核心数)。
if 块对应 主应用。
如果 它 崩溃——整个系统都会挂掉。
但如果某个工作进程崩溃呢?父进程会检测到并启动一个新进程。
这就是整个技巧所在。
何时使用集群
当您需要以下情况时,集群具有极强的威力:
- 故障隔离
- 崩溃恢复
- 即使单个进程出现故障,也能保持运行的长期系统
只要希望您的 Node.js 服务具备 抗崩溃 和 自我修复 能力,就可以使用它们。
更多内容
如果你想了解细节,Node.js 文档值得一读。
文章
代码库
感谢阅读!