在Node.js中模拟线程

时间:2013-10-15 15:29:38

标签: javascript node.js

我有一个Node.js应用程序,它基本上缓存来自Web服务的数据。 我还有一个队列,它接收大约500个需要尽快处理的项目。通过处理,我的意思是它们中的每一个代表一个HTTP请求以及它的缓存响应。

现在,Node的单线程架构并不适合这种情况。理想情况下,我想生成5-10个“线程”来尽快处理队列。我读到有一个child_process模块可以分叉进程,但我从未使用它。这个模块能帮忙吗?

有人可以为这个问题提出解决方案吗?

2 个答案:

答案 0 :(得分:2)

child_processes只是运行相同或不同脚本的新节点进程的分支。 您可以使用该API来生成系统进程,但这不是我将在此处描述的内容。

它们表现得像真正的nodejs进程,因为它们就是这样。

有一个很大的负面影响:

你需要记住,产生一个节点进程需要花费大量的时间和资源,因此通常可以更快地在一个节点进程中计算数据,或者生成工作者子进行通信工作。正如您在文档中看到的那样,您可以从child_process发送和接收数据,这使您能够将工作委派给已经生成的孩子。

子进程通常与生成它的进程共享相同的stdin和stdout,除非您更改它。只需看看文档。它有很好的文档记录,易于使用。

child_process documentation

我从来没有让工人生孩子,但是我做了这样的事情,你可能认为这很有用。

if (process.argv.indexOf("child") == -1) {
  process.chdir(module.filename.replace(/\/[^\/]+$/, ""));
  var child;
  var spawn = function () {
    console.log("spawning child process " + new Date());
    child = require("child_process").fork(module.filename, ["child"]);
    child.on("close", function () {
      spawn();
    });
  }
  spawn();

  process.on("exit", function () {
    child.kill();
  });
  return;
}

// child code begins here

var fs = require("fs");

fs.watch(process.argv[1], function () {
  process.exit();
});

答案 1 :(得分:0)

child_process模块​​会有所作为。

唯一的问题是,您实际上会产生新进程,因此,您需要考虑内存开销。假设您希望在同一文件中定义子例程的优雅,可以将JavaScript字符串传递给node命令。

所以这正是我们要做的。但首先,让我们创建一个接受JSON兼容对象和函数的函数,然后在新线程上运行该函数:

var child_process = require('child_process');

function startThread(data, fn, callback) {
  var fnStr = '(' + fn.toString() + ')(' + JSON.stringify(data) + ');';

  var node = child_process.spawn('node', ['-e', fnStr]);

  var output = [];

  var onData = function (data) {
    output.push(data.toString('utf8').trim());
  };

  node.stdout.on('data', onData);
  node.stderr.on('data', onData);

  node.on('close', function (code) {
    callback(code, output);
  });
}

作为一个例子,我们将产生一个新线程来生成“99瓶啤酒”的歌词:

startThread({ doFor: '99' }, function (data) {
  var str = '';
  while (data.doFor) {
    str += data.doFor + ' bottles of beer on the wall ' + data.doFor +
    ' bottles of beer. You take one out, toss it around, ';
    data.doFor--;
    str += data.doFor + ' bottles of beer on the wall\n';
  }
  console.log(str.trim());
}, function (code, outputs) {
  console.log(outputs.join(''));
});

不幸的是,将在另一个“线程”中使用的函数无法访问父线程中的变量。

此外,数据通过STDOUT和STDERR传递。