首页 > 解决方案 > Node.js 集群 - 为什么脚本在没有明显原因的情况下多次运行?

问题描述

所以我把下面的代码写到了一个MyScript.js文件中;(直接取自https://nodejs.org/api/cluster.html的 node.js 文档)

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

console.log("I'm at the top"); //PAY ATTENTION TO THIS LINE

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

当我运行它时

>node MyScript.js

,它在命令提示符下输出以下内容:

I'm at the top...
Master 24632 is running
I'm at the top...
Worker 25536 started
I'm at the top...
Worker 17524 started
I'm at the top...
Worker 19020 started
I'm at the top...
Worker 11352 started

它如何同时运行 IF 部分和 ELSE 部分?导致 MyScript.js 多次运行的魔力在哪里?!

更新:tl;博士; 我想出的真正答案是“魔法”的发生,因为 cluster.fork() 在效果中说:创建一个新环境(V8)来执行由 process.argv[1] 定义的“一些 javascript 模块”;这恰好是 MyScript.js 的完整路径;

标签: node.jsnode-cluster

解决方案


将集群视为分叉进程,当您进行for迭代时,您将创建多个fork将运行相同脚本的子进程(部分),但是当他们检查if语句时,他们将执行else部分,因为集群的主进程(即只有一个)是创建现在正在检查if.

运行的进程数与您计算机上的 CPU 数相同,因此,例如,如果您的 CPU 有 8 个内核,则您希望有 8 个工作线程在运行。

所以基本上,你希望只运行一次以下

console.log(`Master ${process.pid} is running`);

// Fork workers.
for (let i = 0; i < numCPUs; i++) {
  cluster.fork();
}

cluster.on('exit', (worker, code, signal) => {
  console.log(`worker ${worker.process.pid} died`);
});

但以下数倍(与您计算机中的 CPU 数量一样多,因为您以这种方式配置它)

// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
  res.writeHead(200);
  res.end('hello world\n');
}).listen(8000);

console.log(`Worker ${process.pid} started`);

然后,当子进程(不是主进程)完成时,您将看到以下内容console.log

console.log(`worker ${worker.process.pid} died`);

编辑:

那么为什么它会运行console.log("I'm at the top");多次?Node 所做的(与 C 不同)是,当它执行 a 时,fork它会创建 V8 引擎的新实例,并且每次创建新进程时都会使代码完全执行。函数名称fork具有误导性,因为它不会复制您的进程并从您所在的位置开始运行,而是生成一个新进程,从而使该进程再次运行整个脚本。


推荐阅读