Подтвердить что ты не робот

Node.js - отправка большого объекта в child_process выполняется медленно

Мой случай использования выглядит следующим образом: Я делаю много вызовов API с моего сервера node для публичных API. Когда-то ответ большой, а иногда и небольшой. Мой прецедент требует от меня отменить ответ JSON. Я знаю большой JSON, поскольку ответ блокирует мой цикл событий. После некоторых исследований я решил использовать child_process.fork для анализа этих ответов, так что другие вызовы API не должны ждать. Я попытался отправить большой 30-мегабайтный JSON файл из моего основного процесса в раздвоенный child_process. Для детского процесса требуется так много времени, чтобы выбрать и разобрать json. Ответ, ожидаемый от детского процесса, не огромен. Я просто хочу выровнять и получить длину и отправить обратно в основной процесс.

Im прикрепляет главный и дочерний код.

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, которая затягивает вещи.

4b9b3361

Ответ 1

Кажется, что ваша задача связана как с IO-привязкой (с размером JMON размером 30 МБ), где сияет асинхронность Node, так и с привязкой к процессору (синтаксический анализ JSON размером 30 МБ), где асинхронность не помогает.

Слишком большое количество процессов вскоре превратится в ресурсоемкую работу и ухудшит производительность. Для задач, связанных с процессором, вам нужно столько процессов, сколько у вас есть ядра и не более.

Я бы использовал один отдельный процесс, чтобы выполнить выборку и делегировать синтаксический разбор N другим процессам, где N - это (самое большее) количество ваших ядер процессора минус 1 и использование некоторой формы IPC для связи процесса.

Один из вариантов состоит в том, чтобы использовать Node Cluster module для организации всего вышеперечисленного: https://nodejs.org/docs/latest/api/cluster.html

Используя этот модуль, вы можете запустить мастер-процесс для своих рабочих процессов, и не нужно беспокоиться о том, когда нужно использовать fork, сколько процессов для создания и т.д. IPC работает как обычно с process.send и process.on. Таким образом, возможен рабочий процесс:

  • Запуск приложения: мастер-процесс создает процессы "сборщик" и "парсер" N.
  • fetcher отправляется рабочий список конечных точек API для обработки и запускает выборку JSON, отправляя ее обратно в мастер-процесс.
  • на каждом JSON выбирается главный отправитель в процесс парсера. Вы можете использовать их круговым способом или использовать более сложный способ передачи сигналов мастер-процессу, когда очередь работы парсера пуста или работает на низком уровне. Процессы парсера
  • отправляют результирующий объект JSON обратно в master.

Обратите внимание, что IPC также имеет нетривиальные служебные данные, особенно при отправке/получении больших объектов. Вы даже можете заставить сборщика выполнять синтаксический анализ очень маленьких ответов, а не передавать их, чтобы избежать этого. "Маленький" здесь, вероятно, 32KB.

См. также: Это дорого или эффективно отправлять данные между процессами в Node?