3

查看nodejs域文档页面中给出的示例:http ://nodejs.org/api/domain.html ,使用集群重启worker的推荐方法是在worker部分调用first disconnect,并监听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. 我在错误时执行了第二次获取请求(30 秒之前)

    • 新计时器开始
    • 服务器已经关闭 => 抛出错误
    • 错误在“catch”块中被捕获,并且没有结果被发送回客户端,因此在客户端,页面正在等待,没有任何消息。

在我看来,最好只是杀死工人,然后在 master 部分听 'exit' 事件再次分叉。这样,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 回调之前,所有后续请求都将触发相同的异常。
4

2 回答 2

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 再发出 1 个请求,服务器无法关闭。

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

于 2013-12-06T15:18:15.187 回答
0

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

于 2014-10-01T21:33:13.273 回答