使用fork的子进程传递和访问请求响应对象

问题描述:

我想知道如何使用fork将父进程的请求响应对象传递给子进程。 我所做的是使用fork的子进程传递和访问请求响应对象

var child = cp.fork(__dirname + '/childProcess.js', req, res); 
child.on('message', function(m) 
{ 
    console.log("child process returned data " + m); 
}); 
child.send("hello"); 

childProcess.js

var req = process.argv[2]; 
var res = process.argv[3]; 
process.on('message', (msg) => 
{ 
    console.log("req object :-" + req); 
    console.log("res object :-" + res); 
} 
process.send("callparent"); 

这使我在子进程不确定。我也尝试过child.send(“hello”,req.socket)。但后来我无法访问子进程中的请求方法。它显示为圆形结构。

按照docs

child.send(消息[,sendHandle] [,回调])

其可以被传递给child.send()可选sendHandle参数是用于使TCP服务器或套接字对象到子进程。子对象将作为第二个参数传递给在process.on('message')事件中注册的回调函数。

这表明,你应该在child.send()功能发送reqreq.socket对象。

另外,您没有从登录到process.on('message')事件的函数的第二个参数访问reqreq.socket对象。

您创建一个服务器,并向客户端发送句柄。 如果使用快递例如,你可以这样做:

Server.js

child= require('child_process').fork('child.js');  
const server = require('net').createServer(); 
server.on('connection', function(socket) {  
    child.send('handle', socket); 

}).listen(80); 

然后创建一个孩子,并接受手柄:

Child.js

var app=require('express')() 
app.get('/',function(req,res){ 
    console.log(req.headers) 
    res.send('Working!') 
}) 

var myServer=require('http').createServer(app) 
process.on('message', function(m, server) { 
    if (m === 'handle') myServer.listen(handle) 
}); 

更多信息:

+0

感谢您的建议..我做了你说的话,但我怎么能访问REQ Res对象在子进程..另外我想要request.headers在子进程。你知道如何去做吗? –

+0

定期像任何明确的应用程序。 'app.get('/',function(req,res){})'。关于请求标题,你可以在不同的问题中提问:)你可以使用req.headers来获取它。 – Aminadav

+0

编辑和添加有关res,res和标题的信息 – Aminadav

其他的答案告诉你套接字发送到儿童和有孩子听和处理请求,这不是被问到的问题(如何将req/res发送给孩子)。如果您的目标是将套接字传递给孩子并让孩子监听并处理请求,那么这些答案都可以。如果您的目标是在主流程中侦听并预处理请求,并将这些请求传递给子进程以供进一步处理,请参阅:

简而言之,您必须实际明确发送请求并回应孩子的过程(他们不会神奇地出现在孩子的过程中)。但是有一些挑战。

在我们的应用程序中,我们有类似的问题。我们的主请求处理器检查请求以查看哪个子进程应该处理每个请求,然后将该请求发送给子进程(通过child.send())。

在父和子之间传递请求/响应的问题是您必须能够序列化与send来回发送的对象,并且特别是请求对象不能被序列化(它充满了循环引用,引用许多其他对象等)。

因此,我们所做的是将数据的子集拉出子进程需要的请求,并且我们通过child.send()将该“轻量级请求”对象发送给子进程,同时保留对原始请求的引用队列在父进程上。当子进程完成处理时,它通过parent.send()将其响应数据发送回父节点,并且父节点与未决队列中原始请求一起匹配,并使用响应数据满足请求。

这种方法的优点(与在父/子之间创建自定义协议相反)是子请求处理代码仍然在请求/响应对象(只是它们的轻量级版本)上运行。在我们的例子中,这意味着我们可以使用相同的请求处理代码,不管我们是在子进程中调用它,还是让进程直接监听和处理请求。

例如,下面是如何使一个轻量级的,序列化的请求对象并将其发送到子进程:

var requestData = 
{ 
    httpVersion: request.httpVersion, 
    httpVersionMajor: request.httpVersionMajor, 
    httpVersionMinor: request.httpVersionMinor, 
    method: request.method, 
    url: request.url, 
    headers: request.headers, 
    body: request.body 
} 
child.send(requestData); 

你也可以只使用像lodash pick东西抓住你想要的字段。

这个解决方案的一个棘手部分是,如果您需要调用请求/响应的任何方法,您必须在父对象(实际对象所在的位置 - 所有子对象都是选定数据)中执行此操作。

+0

知道您在父进程的队列中保留对原始请求的引用会很有趣。 –

+0

我们使用我们自己的异步操作管理器实现来保存完成状态(并处理超时)。这里是代码(开源,随意使用): https://github.com/SynchroLabs/SynchroServer/blob/master/SynchroServer/node_modules/synchro-api/lib/async-ops-mgr.js 如果您对我们如何使用该产品感兴趣,请参阅: https://github.com/SynchroLabs/SynchroServer/blob/master/SynchroServer/node_modules/synchro-api/lib/api-request-delegator.js# L154 如果有人想要,我很乐意将npm模块制作出来。 – BobDickinson