簡體   English   中英

為什么Node cluster.fork()在作為模塊實現時分支父作用域

[英]Why is Node cluster.fork() forking the parent scope when implemented as a module

我正在嘗試實現一個使用cluster的Node模塊。 問題是整個父作用域與預期的集群代碼一起分叉。 我在Mocha中為模塊編寫測試時發現了它:測試套件將運行多次,而不是一次。

如下所示,myModule.js創建N個worker,每個CPU一個。 這些工作者是http服務器,或者可能是其他任何工作者。

每次運行test.js時,腳本都會運行N + 1次。 在下面的示例中,console.log在我的四核上運行了5次。

有人可以解釋這是實施問題還是群集配置問題? 有沒有辦法限制fork()的范圍而不必導入模塊(如在這個解決方案https://github.com/mochajs/mocha/issues/826 )?

/// myModule.js ////////////////////////////////////

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

var startCluster = function(){

  if (cluster.isMaster) {
    // CREATE A CLUSTER OF FORKED WORKERS, ONE PER CPU
    //master does not listen to UDP messages.

    for (var i = 0; i < numCPUs; i++) {

      var worker = cluster.fork();
    }


  } else {
    // Worker processes have an http server.
    http.Server(function (req, res){
      res.writeHead(200);
      res.end('hello world\n');
    }).listen(8000);

  }

  return
}

module.exports = startCluster;

/////////////////////////////////////////////////

//// test.js ////////////////////////////////////

var startCluster = require('./myModule.js')

startCluster()

console.log('hello');

////////////////////////////////////////////////////////

所以我會冒險回答。 仔細觀察節點文檔,有一個cluster.setupMaster可以覆蓋默認值。 cluster.fork()的默認設置是執行當前腳本,“工作文件的文件路徑。(默認= process.argv [1])” https://nodejs.org/docs/latest/api/cluster的.html#cluster_cluster_settings

因此,如果另一個模塊正在使用cluster.fork()調用導入腳本,它仍將使用process.argv [1]的路徑,該路徑可能不是您期望的路徑,並且會產生意想不到的后果。

因此,我們不應該在官方文檔建議的同一文件中初始化集群主服務器和工作服務器。 將工作者分成新文件並覆蓋默認設置是明智的。 (為了安全起見,您可以使用__dirname添加目錄路徑)。

cluster.setupMaster({ exec: __dirname + '/worker.js',});

所以這將是更正的實現:

/// myModule.js ////////////////////////////////////

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

var startCluster = function(){
  cluster.setupMaster({ 
    exec: __dirname + '/worker.js'
  });

  if (cluster.isMaster) {
    // CREATE A CLUSTER OF FORKED WORKERS, ONE PER CPU    
    for (var i = 0; i < numCPUs; i++) {
       var worker = cluster.fork();
    }

  } 
  return
}

module.exports = startCluster;

/////////////////////////////////////////////////

//// worker.js ////////////////////////////////////
var http = require('http');

// All worker processes have an http server.
http.Server(function (req, res){
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);

////////////////////////////////////////////////////////

//// test.js ////////////////////////////////////

var startCluster = require('./myModule.js')

startCluster()

console.log('hello');

////////////////////////////////////////////////////////

您應該只看到'hello'一次而不是1 * CPU數量

你需要在代碼的頂部放置“isMaster”,而不是在函數內部。 worker將從模塊的頂部運行(它不像C ++ fork,worker在fork()點開始)。

我假設你想要startCluster = require('。/ cluster-bug.js')只進行一次eval? 好吧,那就是因為你的整個腳本都是集群的。 你在startCluster中指定的只是讓它在主集群和從集群之間變化。 群集生成初始化文件的fork。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM