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