繁体   English   中英

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

[英]Node.js - Sending a big object to child_process is slow

我的用例如下:我从节点服务器到公共API进行了大量的休息API调用。 有时响应很大,有时很小。 我的用例要求我对响应JSON进行字符串化。 我知道一个大的JSON,因为响应将阻止我的事件循环。 经过一些研究后,我决定使用child_process.fork来解析这些响应,以便其他API调用不需要等待。 我尝试从我的主进程发送一个30 MB的大JSON文件到分叉的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),其中异步性对您没有帮助。

分叉太多流程很快就会成为资源困境并降低性能。 对于CPU绑定的任务,您需要的核心数量与核心数量相同,而不是更多。

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

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

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

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

请注意,IPC也有非平凡的开销,特别是在发送/接收大对象时。 您甚至可以让提取器对非常小的响应进行解析,而不是传递它们以避免这种情况。 这里的“小”大概是<32KB。

另请参阅: 在节点中的进程之间发送数据是否昂贵/高效?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM