管理多节点子进程



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

在此示例中,可以多次调用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
}

更新

根据一些评论,我尝试了这个。 但是,如果我启动 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()时,没有错误。 问题是子进程没有被杀死:

服务器.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
}

索引.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');
}

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

您可以在此处查看 ChildProcess 对象的事件和方法。 还有许多代码示例。

为了向子进程发送消息,请使用以下示例:

父.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' });

**

孩子.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

最新更新