管理多节点子进程

时间:2017-06-23 07:16:34

标签: node.js child-process

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

在此示例中,可以多次调用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()时,没有错误。问题是子进程没有被杀死:

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:-1)

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

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