在Node模块中使用cluster

Chr*_*son 6 multithreading cluster-computing node.js

更新:即使这个特定场景不切实际,根据评论,我仍然感兴趣的是如何编写一个使用群集的模块,而不必每次都重新运行父进程.


我正在尝试编写一个名为Node.js的模块mass-request,通过将它们分发给子进程来加速大量的HTTP请求.

我希望,在外面,它的工作方式就是这样.

var mr = require("mass-request"),
    scraper = mr();

for (var i = 0; i < my_urls_to_visit.length; i += 1) {
    scraper.add(my_urls_to_visit[i], function(resp) {
        // do something with response
    }
}
Run Code Online (Sandbox Code Playgroud)

首先,我为群发请求模块组建了一个骨架.

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

module.exports = function() {
    console.log("hello from mass-request!");
    if (cluster.isMaster) {
        for (var i = 0; i < numCPUs; i += 1) {
            var worker = cluster.fork();             
        }

        return {
            add: function(url, cb) {}       
        }       
    } else {
        console.log("worker " + process.pid + " is born!");
    }  
}
Run Code Online (Sandbox Code Playgroud)

然后我在测试脚本中测试它:

var m = mr();
console.log("hello from test.js!", m);
Run Code Online (Sandbox Code Playgroud)

我期望看到"大众要求你好!" 记录了四次(实际上是这样).令我惊讶的是,我也四次看到"来自test.js的问候".显然我不明白它是如何cluster.fork()运作的.它是否重新运行整个过程,而不仅仅是第一次调用它的函数?

如果是这样,如何在模块中使用群集而不会让使用该模块的人遇到麻烦的多进程逻辑?

dc5*_*dc5 4

我相信你要找的东西就在setupMaster中

来自文档:

cluster.setupMaster([设置])

  • 设置对象
    • exec 工作文件的字符串文件路径。(默认=process.argv[1])
    • args 传递给worker的数组字符串参数。(默认=process.argv.slice(2))
    • silent Boolean 是否将输出发送到父级的 stdio。(默认=假)

setupMaster 用于更改默认的“fork”行为。调用后,设置将出现在 cluster.settings 中

通过使用 exec 属性,您可以从不同的模块启动您的工作程序。

重要提示:正如文档所述,只能调用一次。如果您的模块依赖于这种行为,那么调用者就无法使用cluster,或者整个事情就会崩溃。

例如:

索引.js

var cluster = require("cluster"),
  path = require("path"),
  numCPUs = require("os").cpus().length;

console.log("hello from mass-request!");
if (cluster.isMaster) {
  cluster.setupMaster({
    exec: path.join(__dirname, 'worker.js')
  });

  for (var i = 0; i < numCPUs; i += 1) {
    var worker = cluster.fork();
  }

  return {
    add: function (url, cb) {
    }
  }
} else {
  console.log("worker " + process.pid + " is born!");
}
Run Code Online (Sandbox Code Playgroud)

工人.js

console.log("worker " + process.pid + " is born!");
Run Code Online (Sandbox Code Playgroud)

输出

node index.js 
hello from mass-request!
worker 38821 is born!
worker 38820 is born!
worker 38822 is born!
worker 38819 is born!
Run Code Online (Sandbox Code Playgroud)

  • 那行“return{add: function(url,cb){}}”在做什么? (2认同)