2017-06-23 75 views
1

如何管理已分叉的多个并发子进程?管理多个节点子进程

在此示例中,可以多次调用start_child(),并且每个调用都可以无限期地运行。当像这样分配任意数量的子进程时,如何与每个子进程通信/处理?假设我有3个分叉的子进程正在运行,并且它们会一直运行,但我想要杀死(或发送消息)到子进程号2.我该怎么做?

如果调用stop_child(),它会杀死所有当前正在运行的子进程。如何重构此代码,以便我可以在个别子进程上调用stop_child()

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function() { 
     start_child(); 
    }); 

    socket.on('stop_child', function() { 
     child.kill(); 
    } 
} 

function start_child() { 
    child = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

UPDATE

我想这一点,基于一些评论。但是,如果我启动3个进程然后调用,例如,child[0].kill(),则会出现错误:Cannot read property 'kill' of undefined。我猜我的问题是,我没有正确地传递i变量的io.on()电话:

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 
let i  = 0; 
let child = []; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function (i) { 
     start_child(i++); 
    }); 

    //this is hard coded just for testing 
    socket.on('stop_child', function() { 
     child[0].kill(); 
    } 
} 

function start_child(i) { 
    child[i] = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

更新#2

好吧,我想通了,我需要从客户端发送增量变量,通过来自emit调用的对象。现在,当我拨打child[0].kill()时,没有错误。问题是,子进程没有中止:

server.js

let app  = require('express')(); 
let server = require('http').Server(app); 
let io  = require('socket.io')(server); 
let fork = require('child_process').fork; 

server.listen(80); 

app.get('/', function(request, response) { 
    response.sendFile(__dirname + '/index.html'); 
}); 

io.on('connection', function(socket) { 
    socket.on('start_child', function (count) { 
     let num = count.count; 
     start_child(num); 
    }); 

    //this is hard coded just for testing 
    socket.on('stop_child', function (count) { 
     let num = count.count; 
     child[num].kill(); 
    } 
} 

function start_child(num) { 
    child[num] = fork('./child_script.js'); 

    //conditional logic to either run 
    //start_child() again or let it end 
} 

的index.html

$(function() { 
    let socket = io(); 
    let i  = 0; 

    $('#start').on('click', function() { 
     socket.emit('start_child', {"count": i++}); 
    }); 

    $('#stop').on('click', function() { 
     //the count is hard coded here just for testing purposes 
     socket.emit('stop_child', {"count": 0}); 
    }); 
}); 

最后更新 - 分辨率

分辨率#2(正上方)实际上是解决方案。我之后遇到的问题(其中child.kill()调用似乎没有做任何事情)是由我遗漏的一段代码引起的(在代码注释中:'条件逻辑再次运行start_child()或让它结束')。

这是什么在那里:

if (condition) { 
    setTimeout(start_child, 5000); 
} else { 
    console.log('this child process has ended'); 
} 

而这就是我改成了(基本上,我不得不递增变量传递给start_child()功能,使得它会在同一个地方所述child阵列时,它重新启动):

if (condition) { 
    setTimeout(function() { 
     start_child(num) 
    }, 5000); 
} else { 
    console.log('this child process has ended'); 
} 
+0

什么操作系统是服务器上运行的,什么是你的child_script做。它在'child.kill()'doc的文档中说过:***请注意,虽然函数被称为kill,但传递给子进程的信号可能不会真正终止进程。***您还应该记录' child.on('error',...)'如果传递kill消息时发生错误。 – jfriend00

+0

目前,它运行在Windows上的Cygwin环境中。 – CJG

回答

1

fork()返回其具有对象与该进程间通信上的方法和事件子进程对象。因此,您必须在调用start_child()时保存每个ChildProcess对象,然后使用适当的对象与其他进程通信。

你可以看到事件和子进程对象here的方法。还有很多代码示例。

+0

我明白'fork()'返回一个ChildProcess对象,并且我已经阅读了文档。我只是不清楚如何解决特定的子对象(当多个孩子被分叉时),或者我需要重构示例代码才能实现这一点。 – CJG

+0

@CJG - 很难理解问题所在。如果你打开5个子进程,你可以将它们保存在一个数组中。要与第一个进行通信,您需要从数组的第一个元素获取ChildProcess对象,并使用该特定的“ChildProcess”对象与该特定的子进行通信。 – jfriend00

+0

@CJG - 您是否试图从父母向特定孩子或从特定孩子向另一个特定孩子发送消息? – jfriend00

0

为了发送消息,子进程,使用下面的示例:

parent.js

**

const { fork } = require('child_process'); 
const forked = fork('child.js'); 
forked.on('message', (msg) => { 
    console.log('Message from child', msg); 
}); 
forked.send({ hello: 'world' }); 

**

child.js

process.on('message', (msg) => { 
    console.log('Message from parent:', msg); 
}); 

let counter = 0; 

setInterval(() => { 
    process.send({ counter: counter++ }); 
}, 1000); 

欲了解更多信息,请参阅这篇文章:

https://medium.freecodecamp.com/node-js-child-processes-everything-you-need-to-know-e69498fe970a

+0

我知道如何在父母和孩子之间来回发送消息。我不知道的是当家长有多个孩子时,如何向特定的孩子发送消息。 – CJG

+0

您需要在父级侧记住子节点,比如将子对象存储在数组中,然后调用适当的子对象方法 – ramasCoder

+0

您能给我一个简单的例子吗?我需要能够在特定的孩子上调用'kill()'。由于当前编写的代码,如果我调用'child.kill()',那么所有的子进程都会被终止。我得到每个子节点都必须在父节点上记住;我只是不太清楚如何使用这段代码来做到这一点。 – CJG