Javascript (node.js) child 个进程的上限数量

Javascript (node.js) capped number of child processes

希望我能清楚地描述我正在寻找的东西。使用 Node 和 Python.

我正在尝试 运行 多个 child 进程(.py 脚本,使用 child_process.exec())并行,但一次不超过指定数量时间(例如,2)。我分批收到数量未知的请求(假设这批有 3 个请求)。我想停止生成进程,直到当前进程之一完成。

for (var i = 0; i < requests.length; i++) {

    //code that would ideally block execution for a moment
    while (active_pids.length == max_threads){
        console.log("Waiting for more threads...");
        sleep(100)
        continue
    };

    //code that needs to run if threads are available
    active_pids.push(i);

    cp.exec('python python-test.py '+ requests[i],function(err, stdout){
        console.log("Data processed for: " + stdout);

        active_pids.shift();

          if (err != null){
              console.log(err);
          }
    });
}

我知道 while 循环不起作用,这是第一次尝试。

我猜有一种方法可以做到这一点

setTimeout(someSpawningFunction(){

    if (active_pids.length == max_threads){
        return
    } else {
        //spawn process?
    }

},100)

但我无法完全理解它。

或者也许

waitpid(-1)

在上面的 for 循环中插入 if 语句代替 while 循环?但是我现在无法安装 waitpid() 模块。

是的,我知道阻塞执行在 JS 中被认为是非常糟糕的,但就我而言,我需要它发生。如果可能的话,我宁愿避免使用外部集群 manager-type 库。

感谢您的帮助。

EDIT/Partial 解

一个丑陋的 hack 将使用来自的答案:this SO question (execSync())。但这会阻塞循环,直到 LAST child 完成。这是我目前的计划,但并不理想。

来自 async 库的

async.timesLimit 是在这里使用的完美工具。它允许您异步 运行 一个函数 n 次,但在任何给定时间最多 运行 这些函数并行调用 k 次。

async.timesLimit(requests.length, max_threads, function(i, next){
    cp.exec('python python-test.py '+ requests[i], function(err, stdout){
        console.log("Data processed for: " + stdout);

        if (err != null){
            console.log(err);
        }

        // this task is resolved
        next(null, stdout);
    });
}, function(err, stdoutArray) {
  // this runs after all processes have run; what's next?
});

或者,如果您希望错误是致命的并停止循环,请调用 next(err, stdout)

您可以只维护一个等待 运行 的外部进程队列和一个当前 运行 有多少进程的计数器。队列将简单地为每个进程包含一个对象,该对象的属性包含您需要知道哪个进程要 运行 的数据。您可以只将这些对象的数组用于队列。

每当收到对 运行 外部进程的新请求时,将其添加到队列中,然后启动外部进程,每次启动时都会增加计数器,直到计数器达到最大数量。

然后,在监视这些外部进程的同时,每当一个进程完成时,您就会减少计数器,如果等待 运行 的任务队列不为空,您将启动另一个进程并再次增加计数器。

async 库内置了这种类型的功能(运行一次执行特定数量的操作),尽管使用队列实现自己并不难,并且一个柜台。关键是你只需要挂钩完成,即使是你的外部进程,这样你就可以维护计数器并启动任何正在等待的新任务。

没有理由需要使用同步或串行执行或阻塞来实现您的目标。