javascript - Node.js - 向 child_process 发送大对象很慢

标签 javascript node.js child-process

我的用例如下: 我从我的 Node 服务器向公共(public) API 进行了大量的 REST API 调用。有时 react 很大,有时 react 很小。我的用例要求我对响应 JSON 进行字符串化。我知道一个很大的 JSON 作为响应会阻塞我的事件循环。经过一番研究,我决定使用 child_process.fork 来解析这些响应,这样其他 API 调用就不需要等待了。我尝试将一个 30 MB 的大 JSON 文件从我的主进程发送到 fork 的 child_process。子进程需要很长时间才能选择和解析 json。我对子进程的期望并不大。我只想字符串化并获取长度并发送回主进程。

我附上了主代码和子代码。

var moment = require('moment');
var fs = require('fs');
var process = require('child_process');
var request = require('request');

var start_time = moment.utc().valueOf();

request({url: 'http://localhost:9009/bigjson'}, function (err, resp, body) {

  if (!err && resp.statusCode == 200) {

    console.log('Body Length : ' + body.length);

    var ls = process.fork("response_handler.js", 0);

    ls.on('message', function (message) {
        console.log(moment.utc().valueOf() - start_time);
        console.log(message);
    });
    ls.on('close', function (code) {
        console.log('child process exited with code ' + code);
    });
    ls.on('error', function (err) {
        console.log('Error : ' + err);
    });
    ls.on('exit', function (code, signal) {
        console.log('Exit : code : ' + code + ' signal : ' + signal);
    });
  }
  ls.send({content: body});
});

response_handler.js

console.log("Process " + process.argv[2] + " at work ");

process.on('message', function (json) {
  console.log('Before Parsing');
  var x = JSON.stringify(json);
  console.log('After Parsing');
  process.send({msg: 'Sending message from the child. total size is' +    x.length});
});

有没有更好的方法来实现我想要做的事情?一方面,我需要 node.js 的强大功能来每秒进行 1000 次 API 调用,但有时我会得到一个很大的 JSON,这会把事情搞砸。

最佳答案

您的任务似乎既受 IO 限制(获取 30MB 大小的 JSON)而 Node 的异步性大放异彩,也受 CPU 限制(解析 30MB 大小的 JSON)而异步对您没有帮助。

fork 过多的进程很快就会占用资源并降低性能。对于 CPU 密集型任务,您需要的进程数与核心数一样多,仅此而已。

我会使用一个单独的进程来进行获取并将解析委托(delegate)给 N 个其他进程,其中 N (最多)是您的 CPU 内核数减 1,并使用某种形式的 IPC 进行进程通信。

一种选择是使用 Node 的 Cluster 模块来编排以上所有内容:https://nodejs.org/docs/latest/api/cluster.html

使用此模块,您可以让主进程预先创建您的工作进程,而无需担心何时 fork 、创建多少进程等。IPC 与 process.send 一样正常工作process.on。所以一个可能的工作流程是:

  1. 应用启动:主进程创建一个“fetcher”和N个“parser”进程。
  2. fetcher 收到要处理的 API 端点的工作列表,并开始获取 JSON 并将其发送回主进程。
  3. 在每个提取的 JSON 上,master 发送到解析器进程。您可以以循环方式使用它们,或者在解析器工作队列为空或运行不足时使用更复杂的方式向主进程发出信号。
  4. 解析器进程将生成的 JSON 对象发送回主服务器。

请注意,IPC 也有不小的开销,尤其是在发送/接收大型对象时。您甚至可以让 fetcher 解析非常小的响应,而不是传递它们来避免这种情况。这里的“小”可能 < 32KB。

另请参阅:Is it expensive/efficient to send data between processes in Node?

关于javascript - Node.js - 向 child_process 发送大对象很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33842489/

相关文章:

javascript - Chart.JS 自定义 y 轴标签,其中包含有值(value)的文本

javascript - 全局命名空间变量?

node.js - 为 node.js Web 服务应用程序安装服务器

javascript - 如何将函数/回调传递给 Node.js 中的子进程?

c - system() 函数,同时 SIGCHLD 被忽略

javascript - 使用 Javascript/JQuery 的下拉列表的日期脚本

Javascript HTML 输入数组 PHP

node.js - 打包后嵌套的node_modules文件夹消失

javascript - jQuery 函数在 CodePen 中有效,但在 Node.js 服务器中无效

PHP 环境变量转移到子进程中