处理http服务器崩溃

时间:2014-09-21 08:47:00

标签: javascript node.js http

我有一个非常基本的http服务器:

require("http").createServer(function (req, res) {
    res.end("Hello world!");                      
}).listen(8080);                                 

如何监听服务器崩溃,以便发送500状态代码作为回应?

process.on("uncaughtException", handler)级别收听process工作,但我没有请求和响应对象。

我看到的一个可能的解决方案是在try - catch回调中使用createServer语句,但我正在寻找是否有更好的解决方案。

我尝试在error对象上侦听server事件,但没有任何反应:

var s = require("http").createServer(function (req, res) {
    undefined.foo; // test crash
    res.end("Hello world!");                      
});
s.on("error", function () { console.log(arguments); });
s.listen(8080);                                 

1 个答案:

答案 0 :(得分:9)

捕获并处理错误

您可以使用节点的内置domain module

  

域提供了一种处理多个不同IO操作的方法   单组。如果注册了任何事件发射器或回调   域发出错误事件,或抛出错误,然后域   将通知对象,而不是丢失错误的上下文   在process.on('uncaughtException')处理程序中,或导致程序   立即退出并显示错误代码。

需要注意的一件非常重要的事情是:

  

域错误处理程序不能代替在发生错误时关闭进程。

     

就如何在JavaScript中使用throw的本质而言,几乎就是这样   从来没有任何方法安全地“拿起你离开的地方”,没有泄漏   引用,或创建一些其他类型的未定义的脆弱状态。

由于您只询问如何回应500错误,我不会像节点文档那样处理如何处理重启服务器等问题。 我强烈推荐taking a look at the example in the node docs 。 他们的示例演示了如何捕获错误,将错误响应发送回客户端(如果可能),然后重新启动服务器。我只会显示域名创建并发回500错误响应。 (请参阅有关重新启动流程的下一部分)

域名的作用与try / catch createServer回调相同。在你的回调中:

  1. 创建新的域对象
  2. 聆听域名error事件
  3. reqres添加到域中(因为它们是在域存在之前创建的)
  4. run域并调用您的请求处理程序(这类似于try / try的{​​{1}}部分)
  5. 这样的事情:

    catch

    错误后重新启动进程

    通过使用var domain = require('domain'); function handleRequest(req, res) { // Just something to trigger an async error setTimeout(function() { throw Error("Some random async error"); res.end("Hello world!"); }, 100); } var server = require("http").createServer(function (req, res) { var d = domain.create(); d.on('error', function(err) { // We're in an unstable state, so shutdown the server. // This will only stop new connections, not close existing ones. server.close(); // Send our 500 error res.statusCode = 500; res.setHeader("content-type", "text/plain"); res.end("Server error: " + err.message); }); // Since the domain was created after req and res, they // need to be explictly added. d.add(req); d.add(res); // This is similar to a typical try/catch, but the "catch" // is now d's error event. d.run(function() { handleRequest(req, res); }); }).listen(8080); 模块,您可以在发生错误后很好地重新启动进程。我基本上是从这里的节点文档复制示例,但一般的想法是从主进程启动多个工作进程。 worker是处理传入连接的进程。如果其中一个具有不可恢复的错误(即我们在上一节中捕获的错误),那么它将与主进程断开连接,发送500响应并退出。当主进程看到工作进程断开连接时,它将知道发生了错误并启动了新工作程序。由于有多个工作进程同时运行,因此如果其中一个连接发生故障,则不应该出现丢失传入连接的问题。

    示例代码,从here复制:

    cluster

    注意:我仍然要强调您应该查看domain module documentation并查看其中的示例和说明。它解释了大部分(如果不是全部),背后的原因以及您可能遇到的其他一些情况。