fork 一个子进程并注入依赖

Posted

技术标签:

【中文标题】fork 一个子进程并注入依赖【英文标题】:Fork a child process and inject dependency 【发布时间】:2013-02-28 09:23:51 【问题描述】:

我目前在一个阻塞的模块中有一个操作,所以我正在考虑把它变成一个我 fork 的子进程。

如果我想这样做,那么我当然需要修改我的模块的架构。模块要求通过调用模块作为函数来注入依赖项,并传入依赖项,如下所示:

var dependency =  name: "Bob" 
require('worker')(dependency)

然后在我的worker 模块中:

module.exports = function (dependency) 
  // Outputs  name: "Bob" 
  console.log(dependency)

我怎样才能把这个例子变成一个被分叉的子进程?

【问题讨论】:

fork 一个子节点,然后使用 child.send(message) 从父节点发送依赖。您传递的对象不能是循环的。 nodejs.org/api/… @GabrielLlamas 我稍后需要使用child.send(message) 将数据实际发送给工作人员(而不是依赖项)。我不明白我的工作人员如何区分正在发送的消息类型以及如何处理它们。 好吧,当你接受另一个答案时,我正在做一个完整的例子,看看它! 感谢@GabrielLlamas 【参考方案1】:

使用 .fork() 时,您将启动一个完全独立的进程,因此您无法在父进程和子进程之间传递引用(并且仅限于在创建进程后进行消息传递)。

一种不需要消息传递的方法是在你 fork 进程时传递参数(在一个数组中)。虽然我相信你必须坚持使用简单的字符串/数字值(但从代码中看起来这对你来说可能已经足够了)。例如:

顶层:

var name = 'bob'
var args = [name];
var childProcess = require('child_process').fork(__dirname + '/worker', args);

在工作进程中:

var name = process.argv[2]; //AFIAK elements 0 and 1 are already populated with env info

更新

如果您真的想走消息传递路线(如果您已经需要发送消息,我会毫不犹豫地推荐),那么您可以区分消息类型,如下所示(可能有更优雅的方式):

顶层:

var childProcess = require('child_process').fork(__dirname + '/worker');
childProcess.send(msgtype:'dependencies', content:dependencies);

//Then to send 'normal' message:
childProcess.send(msgtype:'myothermessagetype', content:'some content'

在工作进程中:

process.on('message', function(msg)
    if(msg.mtype == 'dependencies') 
       var dependencies = msg.content;
       //Do something with dependencies
     else if(msg.mtype == 'myothermessagetype') 
       var normalmessage = msg.content;
       //Do something in response to normal message.
    
);

【讨论】:

感谢您提供的信息丰富的回答。不幸的是,我需要传递一个对象……尽管我想我可以将其字符串化。 是的,我个人会进行字符串化,或者,如果它不是太复杂,则暂时将其破解为它的成分。我不喜欢用设置和正常的“运行时”东西使消息传递逻辑复杂化。 执行“node a/b/c/app.js”时失败 @UpTheCreek 你会做后者还是只是字符串化并作为 arg 发送? @GabrielLlamas - 你能提供更多细节吗?你的意思是对worker.js的引用吗? (这只是一个例子)。【参考方案2】:

在主模块中:

var dependency = message: 'hello there';
var args = [JSON.stringify(dependency)];
var child = require('child_process').fork('worker', args);
child.send('sayhello');
child.send('exit');

并在子进程模块(worker.js)中:

var dependency = JSON.parse(process.argv[2]);
process.on('message', function(m)
    if(m == 'sayhello') console.log(dependency.message);
    else if(m == 'exit') process.exit();
);

【讨论】:

【参考方案3】:

a.js

var fork = require ("child_process").fork;
var child;
var init = false;

var m = module.exports = ;
m.init = function (o)
    if (init) return;
    init = true;
    child = fork (__dirname + "/child");
    child.send ( init: o );
;
m.print = function (o)
    if (!init) return;
    child.send ( msg: o );
;
m.uninit = function ()
    if (!init) return;
    child.on ("exit", function ()
        init = false;
    );
    child.kill ();
;

child.js

var dependency;

var print = function (o)
    console.log (o + dependency.name);
;

process.on ("message", function (o)
    if (o.init)
        dependency = o.init;
    else
        print (o.msg);
    
);

b.js

var a = require ("./a");
a.init ( name: "asd" );
a.print ("hi, ");
setTimeout (function ()
    a.uninit ();
, 1000);

打印:嗨,asd

【讨论】:

以上是关于fork 一个子进程并注入依赖的主要内容,如果未能解决你的问题,请参考以下文章

python-subprocess

OS fork 练习

如何在最后一个子 fork() 下打印带有名称和 pid 的子进程

Python 之 subprocess模块

fork 和 signal:如何将信号从父进程发送到特定的子进程

无法从 2 个 forks() 获取 3 个子进程