Node.js域集群工作者断开连接

时间:2013-12-04 17:53:07

标签: javascript node.js cluster-computing node.js-domains

查看nodejs domain doc页面上给出的示例:http://nodejs.org/api/domain.html,使用cluster重新启动worker的推荐方法是在worker部分中调用first disconnect,然后在master部分中监听disconnect事件。但是,如果您只是复制/粘贴给定的示例,您会注意到disconnect()调用不会关闭当前工作程序:

这里发生的是:

try {
    var killtimer = setTimeout(function() {
        process.exit(1);
    }, 30000);
    killtimer.unref();
    server.close();
    cluster.worker.disconnect();
    res.statusCode = 500;
    res.setHeader('content-type', 'text/plain');
    res.end('Oops, there was a problem!\n');
} catch (er2) {
    console.error('Error sending 500!', er2.stack);
}
  1. 我在/ error

    处收到了请求
    • 计时器启动:30秒内,如果还没有
    • ,则该过程将被终止
    • http服务器已关闭
    • 工作人员已断开连接(但仍然活着)
    • 显示500页
  2. 我做错了第二次请求(30s之前)

    • 新计时器已启动
    • 服务器已关闭=>抛出错误
    • 错误被捕获在“catch”块中,并且没有结果发送回客户端,因此在客户端,页面正在等待而没有任何消息。
  3. 在我看来,最好只是杀死工人,并听取主要部分的“退出”事件再次分叉。这样,在错误期间始终发送500错误:

    try {
        var killtimer = setTimeout(function() {
            process.exit(1);
        }, 30000);
        killtimer.unref();
        server.close();
        res.statusCode = 500;
        res.setHeader('content-type', 'text/plain');
        res.end('Oops, there was a problem!\n');
        cluster.worker.kill();
    } catch (er2) {
        console.error('Error sending 500!', er2);
    }
    

    我不确定使用kill而不是断开连接的副作用,但似乎断开正在等待服务器关闭,但似乎这不起作用(至少不应该这样)

    我想要一些关于此的反馈。可能有一个很好的理由这个例子以我错过的方式编写。

    由于

    编辑:

    我刚用curl检查过,效果很好。
    但是我之前使用的是Chrome测试,看起来在发回500响应之后,Chrome会在服务器实际结束关闭之前再发出第二个请求。 在这种情况下,服务器正在关闭而不是关闭(这意味着工作人员也在断开连接而没有断开连接),导致第二个请求由同一个工作人员处理,因此:

    1. 它会阻止服务器完成关闭
    2. 正在评估的第二条server.close();行,它会触发异常,因为服务器未关闭。
    3. 所有后续请求都将触发相同的异常,直到调用killtimer回调。

2 个答案:

答案 0 :(得分:3)

我想通了,实际上当服务器关闭并同时收到请求时,它会停止关闭过程。
所以他仍然接受连接,但不能再关闭了。

即使没有集群,这个简单的例子说明了这一点:

var PORT = 8080;
var domain = require('domain');
var server = require('http').createServer(function(req, res) {
    var d = domain.create();
    d.on('error', function(er) {
            try {
                var killtimer = setTimeout(function() {
                    process.exit(1);
                }, 30000);
                killtimer.unref();
                console.log('Trying to close the server');
                server.close(function() {
                    console.log('server is closed!');
                });
                console.log('The server should not now accepts new requests, it should be in "closing state"');
                res.statusCode = 500;
                res.setHeader('content-type', 'text/plain');
                res.end('Oops, there was a problem!\n');
            } catch (er2) {
                console.error('Error sending 500!', er2);
            }
        });

        d.add(req);
        d.add(res);

        d.run(function() {
            console.log('New request at: %s', req.url);
            // error
            setTimeout(function() {
                flerb.bark();
            });
        });
});
server.listen(PORT);

跑步:

curl http://127.0.0.1:8080/ http://127.0.0.1:8080/ 

输出:

New request at: /
Trying to close the server
The server should not now accepts new requests, it should be in "closing state"
New request at: /
Trying to close the server
Error sending 500! [Error: Not running]

现在单个请求:

curl http://127.0.0.1:8080/

输出:

New request at: /
Trying to close the server
The server should not now accepts new requests, it should be in "closing state"
server is closed!

因此,例如,如果chrome再次向favicon请求,则服务器无法关闭。

现在我将继续使用worker.kill(),这使得工作人员不会等待服务器停止。

答案 1 :(得分:0)

我在6个月前遇到了同样的问题,遗憾的是没有任何代码可以证明,因为它来自我以前的工作。我通过向工作人员显式发送消息并同时调用disconnect来解决它。断开连接会阻止工作人员接受新工作,在我的情况下,因为我正在跟踪工作人员正在做的所有工作(这是上传服务长时间运行的上传)我能够等到所有工作完成然后退出0.