2013-03-05 74 views
2

当所有连接关闭时,此Node.js服务器将在Ctrl + C上完全关闭。使用keepalives进行高效HTTP关机?

var http = require('http'); 
var app = http.createServer(function (req, res) { 
    res.end('Hello'); 
}); 

process.on('SIGINT', function() { 
    console.log('Closing...'); 
    app.close(function() { 
    console.log('Closed.'); 
    process.exit(); 
    }); 
}); 

app.listen(3000); 

问题在于它包含保持连接。如果您在Chrome中为此应用打开了一个标签,然后尝试按Ctrl + C,那么当Chrome终于释放连接时,它将不会关闭约2分钟。

是否有一种干净的方式来检测何时不再有HTTP请求,即使某些连接仍处于打开状态?

+1

您可以关闭侦听套接字,然后立即启动新的服务器吗?然后你可以让它在完成时关闭,不需要多长时间。 – 2013-03-05 16:41:08

+0

如果我在同一个进程中启动一台新服务器,是的,它可以开始监听并接受新的连接。我希望能够在开始新流程之前等待流程停止,但也许这就是我坚持以前的方式。如果没有别的,它在开发过程中很有用。 – Nick 2013-03-05 16:48:03

+1

是的,放手吧。 :)或者,也许放弃keepalive超时5秒。无论如何,这是一个常见的策略,至少对于apache来说。节点明显不同,但它不一定是疯狂的。另外 - 你应该*能够启动一个新的进程并绑定套接字,只要这个套接字已经关闭了。 – 2013-03-05 16:51:47

回答

2

默认情况下,没有套接字超时,这意味着连接将永远打开,直到客户端关闭它们。如果您想设置超时时间,请使用此功能:socket.setTimeout

如果您尝试关闭服务器,您根本无法访问,因为存在活动连接,所以如果尝试正常关闭关闭功能,则会挂起。唯一的办法是设置一个超时时间,并在其到期时杀死该应用程序。

如果你有工作人员,它不像使用process.exit()来杀死应用程序那样简单,所以我创建了一个模块,它可以提供你正在问的问题:grace

+0

你说的对,一般来说,如果一个连接打开,那么它是开放的,而且你要么必须计时或只是无限期地等待。但是特别是对于HTTP,如果连接不会提供任何进一步的HTTP请求,那么它不再是“活动的”,并且可以在此基础上关闭。 – Nick 2013-03-06 08:58:05

+0

尽管您的模块看起来很酷。 – Nick 2013-03-06 10:07:36

+0

我去定义了一个小的请求计数模块,它暴露了一个Express中间件,并且正在为我完成这项工作。不过,请将您的答案标记为正确,因为我喜欢“恩典”的外观,我可能会开始使用它,特别是当我开始使用童工时。 – Nick 2013-03-10 08:52:16

2

你能砍一些要求与finish事件上的反应追踪:

var reqCount = 0; 

var app = http.createServer(function (req, res) { 
    reqCount++; 
    res.on('finish', function() { reqCount--; }); 
    res.end('Hello'); 
}); 

让您检查reqCount是否为零,当你来到关闭服务器。

但是,要做的正确事情可能是不关心旧服务器,只需启动一个新服务器即可。通常重新启动是为了获得新的代码,所以你可以开始一个新的过程,而不用等待旧的过程结束,可以使用child_process模块有一个顶层脚本来管理整个事情。甚至可以使用cluster模块,使您可以在关闭旧模块之前开始新的过程(因为cluster管理其子实例之间的平衡流量)。

我还没有真正测试过很久的一件事,就是一旦server.close()返回,是否可以安全地启动新的服务器。否则,新服务器可能无法绑定。 server.listen()文档中有一个关于如何处理这种EADDRINUSE错误的示例。

+0

这将如何处理多个线程? – CodeCaster 2013-03-05 16:56:27

+0

你说的这些话题是什么? – Nick 2013-03-06 08:49:33

+1

糟糕,[我纠正](http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/)。 – CodeCaster 2013-03-06 09:35:34