我应该使用集群而不是异步来处理 Nodejs 中的并行任务吗?

Should I use clustering instead of asynchronous to handle parallel tasks in Nodejs?

抱歉我的问题很幼稚,我对 Nodejs 还很陌生。

我正在构建一个可以同时处理许多任务的 polling。每个任务可能需要 10 -> 15 秒才能完成。 这是我的 Poller class:

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();

但是如果 handleTask 函数之一失败,Promsie.all 将失败。

我想另一个解决方案是使用 Nodejs 的 worker,并根据我机器上可用的 CPU 核心数进行扩展。每个 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 中处理并行任务的最佳方式是什么?

Node 旨在同时处理许多并发 IO 绑定(数据库查询和 HTTP 调用)。这是在节点运行时通过 event loop and asynchronous IO.

完成的

这意味着在最基本的层面上,您无需执行任何操作即可一次处理数百或数千个 handleTasks

每个 handleTask 调用都会在节点内部将 io 事件排入队列。这允许节点启动一个 handleTask HTTP 调用,然后切换到另一个,再切换到另一个,然后开始接收另一个调用的响应。它可以非常快速地 理想地 完成此操作,您无需担心。

它在内部处理队列中的这些事件,因此如果您有数以万计的并发操作,那么在操作完成时间和节点运行时能够处理该操作的时间之间会有一些延迟损失操作。

在许多常见情况下您必须管理并发:

  • 假设 handleTask 对计量资源进行 HTTP 调用,即速率受限,您需要密切控制和退避此资源
  • 提供您允许进入系统的工作量的上限,以保持可接受的延迟(减载,bulkheading

在 Nodejs 中处理并行任务的最佳方式是什么?

您通常会看到的答案是在任务进入时执行它们并让节点运行时处理它们的调度。就像我提到的,为了确定节点内部事件队列是否为 overloaded.

,您拥有延迟指标(或实施减载或批处理)非常重要

基础阅读: