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
库内置了这种类型的功能(运行一次执行特定数量的操作),尽管使用队列实现自己并不难,并且一个柜台。关键是你只需要挂钩完成,即使是你的外部进程,这样你就可以维护计数器并启动任何正在等待的新任务。
没有理由需要使用同步或串行执行或阻塞来实现您的目标。
希望我能清楚地描述我正在寻找的东西。使用 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
库内置了这种类型的功能(运行一次执行特定数量的操作),尽管使用队列实现自己并不难,并且一个柜台。关键是你只需要挂钩完成,即使是你的外部进程,这样你就可以维护计数器并启动任何正在等待的新任务。
没有理由需要使用同步或串行执行或阻塞来实现您的目标。