我有一个 Node.js 应用程序,它基本上缓存来自 Web 服务的数据。我还有一个队列,它接收大约 500 个需要尽快处理的项目。通过已处理,我的意思是它们中的每一个都代表一个要发出的 HTTP 请求及其要缓存的响应。
现在,Node 的单线程架构并不适合这种场景。理想情况下,我想产生 5-10 个“线程”来尽快处理队列。我读到有一个child_process
可以分叉进程的模块,但我从未使用过它。这个模块有帮助吗?
任何人都可以为这个问题提出解决方案吗?
我有一个 Node.js 应用程序,它基本上缓存来自 Web 服务的数据。我还有一个队列,它接收大约 500 个需要尽快处理的项目。通过已处理,我的意思是它们中的每一个都代表一个要发出的 HTTP 请求及其要缓存的响应。
现在,Node 的单线程架构并不适合这种场景。理想情况下,我想产生 5-10 个“线程”来尽快处理队列。我读到有一个child_process
可以分叉进程的模块,但我从未使用过它。这个模块有帮助吗?
任何人都可以为这个问题提出解决方案吗?
child_processes 只是运行相同或不同脚本的新节点进程的分支。您也可以使用该 api 来生成系统进程,但这不是我将在此处描述的内容。
它们的行为类似于真正的 nodejs 进程,因为它们就是这样。
有一个很大的负面影响:
您需要记住,生成节点进程需要大量时间和资源,因此通常在一个节点进程中计算数据或生成工作子进程以与之通信的速度更快。正如您在文档中看到的那样,您可以从 child_process 发送和接收数据,这使您能够将工作委派给已经生成的子进程。
除非您更改子进程,否则子进程通常与生成它的进程共享相同的标准输入和标准输出。看看文档。它有很好的文档记录并且易于使用。
我从来没有做过工人的孩子,但我做过这样的东西,你可能认为有用。
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();
});
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 传递。