在第一个工作线程结束后结束所有工作线程 Node.js

End all worker threads after the first one ends in Node.js

我目前正在尝试找到一种方法来结束从某个主线程生成的所有工作线程,这些线程中的任何一个完成后。我研究了工作线程之间的各种通信方案(例如 cluster.worker.send()process.send() 等),但其中 none 似乎有效。

到目前为止我的代码非常简单:

const cluster = require('cluster')
const os = require('os')

if ( cluster.isMaster ) {

    let children = []
    for ( let i = 0; i < os.cpus().length; i++ ) {
        children.push(cluster.fork())
    }
    
    process.on('message', (msg) => {
        if ( msg.cmd === 'shutdown' ) {
            console.log('shutting down')
            children.forEach(child => {
                child.kill()
            })
        }
    })

} else {

    console.log('I am worker #' + cluster.worker.id)
    let time = Date.now()
    while ( Date.now() < time + cluster.worker.id * 1000 ) {
        // do nothing for some time
    }
    console.log('I am worker #' + cluster.worker.id + ' and I am done')
    process.send({cmd: 'shutdown'})

}

第一部分使用 cluster 模块为每个 CPU 创建一个子进程。接下来,主进程期望来自任何工作进程的某种关闭消息。每个 worker 运行一些进程,并在一定时间后向主线程发送关闭消息。此时,主线程应该触发所有其他线程关闭,但消息却永远不会收到。这似乎是问题所在,但我一直无法找到发送此消息的方法。

当代码运行时,每个进程都会发送一条 'I am done' 消息,但不会杀死线程。

您需要更改几处内容:

  • 使用 cluster.on 而不是 process.on,因为 process.on 用于子进程,而不是父进程。
  • 使用 child.process.kill() 而不是 child.kill()
const cluster = require('cluster')
const os = require('os')

if ( cluster.isMaster ) {

    let children = []
    for ( let i = 0; i < os.cpus().length; i++ ) {
        children.push(cluster.fork())
    }
    
    cluster.on('message', (worker, msg) => {
        if (msg.command = 'shutdown') {
            // Kill every cluster worker
            children.forEach(child => {
                child.process.kill()
            })
        }
    })

} else {

    console.log('I am worker #' + cluster.worker.id)
    let time = Date.now()
    while ( Date.now() < time + cluster.worker.id * 1000 ) {
        // do nothing for some time
    }
    console.log('I am worker #' + cluster.worker.id + ' and I am done')
    process.send({command: 'shutdown'})
}