【问题标题】:Node.js domain cluster worker disconnectNode.js 域集群工作者断开连接
【发布时间】:2013-12-21 08:32:55
【问题描述】:

查看nodejs域文档页面中给出的示例:http://nodejs.org/api/domain.html,建议使用集群重启worker的方法是在worker部分调用first disconnect,并在master部分监听disconnect事件。但是,如果您只是复制/粘贴给出的示例,您会注意到 disconnect() 调用不会关闭当前的 worker:

这里发生的是:

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 服务器已关闭
    • worker 已断开连接(但仍然存在)
    • 显示500页
  2. 我在错误时执行了第二次获取请求(30 秒之前)

    • 新计时器已启动
    • 服务器已经关闭 => 抛出错误
    • 错误在“catch”块中被捕获,没有结果返回给客户端,所以在客户端,页面正在等待,没有任何消息。

在我看来,最好干掉worker,然后在master部分听'exit'事件再次fork。这样,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 而不是 disconnect 的负面影响,但似乎 disconnect 正在等待服务器关闭,但这似乎不起作用(至少不像它应该的那样)

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

谢谢

编辑:

我刚刚检查了 curl,它运行良好。
但是,我之前使用 Chrome 进行了测试,似乎在发回 500 响应之后,chrome 在服务器实际结束关闭之前执行了第二个请求。
在这种情况下,服务器正在关闭而不是关闭(这意味着工作人员也在断开连接但没有断开连接),导致第二个请求与之前一样由同一个工作人员处理:

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

【问题讨论】:

  • 我遇到了同样的问题,断开连接的工作人员仍然收到请求并且没有关闭。我注意到工作人员在killTimer 到期后关闭,而这不应该发生,因为我们unref 计时器并刚刚完成应该终止工作人员的正常过程。就像 Node.js 文档中所说的那样: // 但不要仅仅为此而保持进程打开! killtimer.unref();
  • 认为它可能取决于节点版本,我无法在link 使用完全相同的代码重现该问题:我的节点版本是 0.10.22(我刚刚更新)可运行节点版本是0.10.12

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


【解决方案1】:

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

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

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() 这使得 worker 不必等待服务器停止。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-23
      • 2016-12-02
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 2016-05-03
      • 2016-10-31
      相关资源
      最近更新 更多