Стоит ли использовать кластеризацию вместо асинхронной для обработки параллельных задач в Nodejs? - PullRequest
0 голосов
/ 21 октября 2019

Извините за мой наивный вопрос, я новичок в Nodejs.

Я создаю polling, который будет обрабатывать много задач одновременно. И каждая задача может занять 10 -> 15 секунд, чтобы закончить. Это мой Poller класс:

class Poller extends EventEmitter {
    constructor(timeout) {
        super();
        this.timeout = timeout;
    }

    poll() {
        setTimeout(() => this.emit("poll"), this.timeout);
    }

    onPoll(fn) {
        this.on("poll", fn); // listen action "poll", and run function "fn"
    }
}

И это мой текущий код внутри каждого poll:

let poller = new Poller(3000); // 3 seconds
poller.onPoll(() => {
    // handle many tasks at the same time
    for (let task of tasks) {
        // handleTask function will take 15 seconds
        // query database, make http request...
        handleTask(task); 
    }
    poller.poll();

})

Если задачи увеличиваются, например, 100 задач,Должен ли я обрабатывать 100 задач одновременно. Или я должен создать пакет для обработки 10 задач одновременно и перейти к следующему опросу, например:

const promises = [];
// 10 tasks only
for (let task of tasks) {
    promises.push(handleTask(task));
}
// wait until finish 10 tasks
await Promise.all(promises);
// go go next poll
poller.poll();

Но Promsie.all не удастся, если произойдет сбой одной из функций handleTask.

И я думаю о другом решении, использующем работника Nodejs и масштабируемом согласно количеству ядер ЦП, доступных на моей машине. Каждая функция handleTask будет работать на каждом работнике:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('death', function(worker) {
    console.log('worker ' + worker.pid + ' died');
  });
}

И еще одна вещь, которую я вижу на некоторых веб-сайтах, использует child_proccess, если я использую child_process, сколько процессов я могу форкнуть? Например:

var cluster = require('cluster');

if (cluster.isMaster) {
  // fork child process for handleTask
  var handleTask1    = require('child_process').fork('./handleTask');
  var handleTask2    = require('child_process').fork('./handleTask');

}

в handleTask.js файле (прослушивание report):

process.on('report', function(data) {
  handleTask(data); // 
});

Как лучше всего выполнять параллельные задачи в Nodejs?

1 Ответ

1 голос
/ 22 октября 2019

Узел был разработан для одновременной обработки множества связанных операций ввода-вывода (запросов к базе данных и HTTP-вызовов). Это достигается во время выполнения узла с помощью цикла событий и асинхронного ввода-вывода .

. Это означает, что на самом базовом уровне вам не нужно ничего делать для обработки сотен или тысячhandleTasks за один раз.

Каждый handleTask вызов будет ставить в очередь события io внутри узла. Это позволяет узлу начать один handleTask HTTP-вызов, затем переключиться на другой, затем переключиться на другой и начать получать ответ на другой вызов. Он делает это очень быстро и в идеале , не беспокоясь об этом.

Внутренне он обрабатывает эти события в очереди, так что, если у вас есть десятки тысяч одновременных операций, тогда будет некоторое задержка между временем завершения операции и временем, которое может выполнить среда выполнения узла. эта операция.

Существует много распространенных ситуаций, когда вам нужно управлять параллелизмом:

  • Предположим, handleTask делает HTTP-вызов с измеряемым ресурсом, т. е. с ограниченной скоростью, вам необходимовнимательно контролируйте и откатывайте этот ресурс
  • Обеспечивая верхнюю границу объема работы, которую вы разрешаете в системе, чтобы поддерживать допустимые задержки (сброс нагрузки, переборка )

Каков наилучший способ обработки параллельных задач в Nodejs?

Ответ, который вы обычно увидите, состоит в том, чтобы выполнить задачи по мере их поступления и позволить узлу работать во время выполнения. обрабатывать планирование их. Как я уже упоминал, очень важно, чтобы у вас были метрики задержки (или реализовать сброс нагрузки или пакетирование), чтобы определить, перегружены ли внутренние очереди событий узла .

Essential Reading:

...