首页 文章

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

提问于
浏览
3

查看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);
}
  • 我在/错误处获取请求

  • 计时器启动:如果没有,30秒内该过程将被终止

  • http服务器已关闭

  • Worker 断线(但仍然活着)

  • 显示500页

  • 我做错了第二次获取请求(30s之前)

  • 新计时器已启动

  • 服务器已关闭=>抛出错误

  • 错误在"catch"块中捕获,并且没有结果发送回客户端,因此在客户端,页面正在等待而没有任何消息 .

在我看来,最好只是杀死 Worker ,并听取主部件上的“退出”事件再次分叉 . 这样,在错误期间始终发送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会在服务器实际结束关闭之前执行第二次请求 .
在这种情况下,服务器正在关闭而不是关闭(这意味着工作人员也在断开连接而不断开连接),导致第二个请求由同一个工作人员处理,因此:

  • 它阻止服务器完成关闭

  • 正在评估的第二个 server.close(); 行,它会触发异常,因为服务器未关闭 .

  • 以下所有请求都将触发相同的异常,直到调用killtimer回调为止 .

2 回答

  • 0

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

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

    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不会等待服务器停止 .

  • 3

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

相关问题