node.js – 如何正确处理子进程中的句柄

前端之家收集整理的这篇文章主要介绍了node.js – 如何正确处理子进程中的句柄前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试构建一个平台来自动部署我在NodeJS中构建的应用程序.
可以从处理这些操作的控制面板启动和停止每个应用程序.
启动应用程序时,控制面板会执行以下操作:

>从以root身份运行的端口绑定器请求句柄.此端口绑定器是控制面板的分叉子节点.
>现在,控制面板将侦听此端口上的请求.收到请求后,它会将客户端套接字的句柄发送给正在侦听“message”事件的应用程序以获取新请求.
>一旦发出应用程序信号,控制面板就会释放对请求和套接字的所有控制权.
>应用程序执行它需要做的事情,并释放和关闭请求和套接字.

此设置很有效,除非尝试关闭不再需要的服务器.
即使服务器发出’close’事件,它仍然接受连接,最终超时,因为不再有requestListener绑定.

我假设有一个没有正确释放的句柄,从而使服务器保持清醒状态.

端口绑定器:

var options = {
    http: require('http'),https: require('https')
};
process.on('message',function( data,handle ) {

    var port = data.port,type = data.type,server;

    server = options[type].createServer();
    server.once('error',function( err ) {
        process.send({success: false,port: port,error: err});
    });
    server.listen(port,function(){
        var handle = server._handle;

        process.send({success: true,port: port},handle);

        server.close();
        handle.close();
        server._handle = null;
        handle = null;
        server.removeAllListeners();
    });
});

控制面板:

var cp = require('child_process'),app,types = {
        http: require('http'),https: require('https')
    },binder = cp.fork('./portbinder');

binder.on('message',handle ) {
    var server = types['http'].createServer(handler);

    server.once('close',function() {
        server._handle = null;
        handle = null;
    });
    server.listen( handle );
});

function handler( req,resp ) {
    app = app || cp.fork('./application'),socket = resp.socket,_handle = socket._handle,_req = {},_resp = {},_socket = {};

    // Copy transferable fields.
    for( i in req ) {
        if( typeof req[i] != 'function' && i != 'socket' && i != 'connection' && i != 'client' ) {
            _req[i] = req[i];
        }
    }

    for( i in resp ) {
        if( typeof resp[i] != 'function' && i != 'socket' && i != 'connection' && i != 'client' ) {
            _resp[i] = resp[i];
        }
    }

    for( i in socket ) {
        if( typeof socket[i] != 'function' &&
            i != '_handle' && i != '_httpMessage' &&
            i != '_idlePrev' && i != '_idleNext' && i != 'server' ) {
                _socket[i] = socket[i];
        }
    }

    // Send request to application.
    app.send({
        type: 'request',data: {
            req: _req,resp: _resp,socket: _socket
        }
    },_handle );

    // Release the handle here without sending anything to the browser.
    socket._write = function() {};
    resp.end();
    socket.destroy();
    socket._handle = null;
    _handle = null;
};

应用:

function reattach( target,properties ) {
    var i;

    for( i in properties ) {
        target[i] = properties[i];
    }

    return target;
};

function handler( req,resp ) {
    resp.end('hello world!');
};

process.on('message',function( param,handle ) {
    var _req = param.data.req,_resp = param.data.resp,_socket = param.data.socket,socket,resp,req;

    // Create a socket and reattach its properties.
    socket = new net.Socket({handle:handle});
    reattach( socket,_socket );

    // Create a request and reattach its properties.
    req = new http.IncomingMessage(socket);
    reattach( req,_req );

    // Create a response and reattach its properties.
    resp = new http.ServerResponse( req );
    resp.assignSocket(socket);
    reattach( resp,_resp );

    // Help closing down sockets after request is handled.
    resp.once('finish',function() {
        socket._write = function() {};
        socket.end();
        socket.destroy();
        socket._handle = null;
        handle = null;
    });

    handler( req,resp );
});

正如您所看到的,我正在尝试null并分离我拥有的所有_handle属性,但服务器句柄不会停止侦听端口.
当我使控制面板有一个未捕获的异常时,它会崩溃,端口绑定器也会这样做.但是应用程序节点进程没有退出并且端口保持绑定,所以我发现我没有正确地释放那些东西,但我无法找到它.

整个设置确实有效,当我提出要求时,它根本就没有关闭服务器.

编辑:我应该注意到我使用的是node.js v0.5.10

解决方法

事实证明,这是对node.js文档的错误解释导致了这个问题.
我使用的浏览器发送了一个keep-alive头,保持连接打开一段时间,以通过相同的连接推送新的请求.

当我做了server.close()时,我希望关闭这些连接,因为文档说:

Stops the server from accepting new connections.

事实证明,保持活动连接没有关闭,所以只要连接打开,浏览器仍然可以做请求,让我知道服务器仍在接受连接.

解决方法是在关闭后将requestListener重新连接到服务器.然后,当您收到连接时,关闭套接字流而不发送任何内容.现在不会处理任何新请求,一旦连接超时,它将关闭,服务器将最终完全关闭.从而为其他用途释放端口.

server.close();
// Drop any new request immediately,while server ditches old connections.
server.on('request',function( req,resp ) { req.socket.end(); });
server.once('close',function(){
    // Remove the listeners after the server has shutdown for real.
    server.removeAllListeners();
});

把这个修复程序放到位我还可以清理我的代码删除代码以释放句柄. node.js垃圾收集器现在正确地拾取句柄对象,当连接死亡时,句柄也是如此.

// All of this is no longer needed.
socket._write = function() {};
socket.end();
socket.destroy();
socket._handle = null;
handle = null;

猜你在找的Node.js相关文章