使用集群构建具备崩溃容错的 Node.js 应用

发布: (2025年12月18日 GMT+8 18:00)
5 min read
原文: Dev.to

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 仍然保持存活。

Trace CLI

参考: 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 文档值得一读。

文章

代码库

感谢阅读!

在此找到我

Back to Blog

相关文章

阅读更多 »