2013-06-30 58 views
9

我有一个nodejs服务器运行快速服务器出http调用。如果出现问题,是否有推荐的方法可以优雅地关闭服务器?我应该让服务器以某种方式运行吗?Nodejs /快递,优雅地关机

I.E.在一个未捕获的例外情况下,服务器只是停止,我认为这会杀死连接的客户端,而不是将它们交还给回应。

我应该:

  1. 等待所有的HTTP连接完成之前,我允许服务器死亡(然后重新启动它)。
  2. 或者我应该试着阻止服务器永生?

这是正确的吗?

process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

在这种情况下,可能已经引发错误而使服务器处于不确定状态,服务器将继续完成了剩余的连接。

有没有什么好的方法来处理错误继续运行,或者我应该让服务器死机并重新启动?

回答

6

不要试图对未处理的异常做任何事情。让服务器死亡。

通常,如果路由处理程序抛出异常,Express将简单地捕获它并向客户端返回HTTP 500。由于Express发现异常,您的服务器不会崩溃。

通常会导致服务器关闭的情况是在回调中引发异常;例如:

app.get('/foo', function(req, res) { 
    db.query(..., function(err, r) { 
     throw new Error(); // oops, we'll crash 
    }); 
}); 

由于回调自然在Express路由器调用堆栈外执行,因此无法将其与特定请求关联。但是,您可以防止这样的情况:

app.get('/foo', function(req, res, next) { 
    db.query(..., function(err, r) { 
     try { 
      throw new Error(); 
     } catch(ex) { 
      next(ex); 
     } 
    }); 
}); 

快车next函数接受一个错误作为第一个参数。如果调用next一个错误的说法,它会停止处理路线,寻找一个error handler,或只返回一个500

当然,在try/catch包装一切可能是矫枉过正;大多数事情实际上并没有抛出异常。你只应该这样做,如果你知道东西可能会抛出你。否则,您可能最终很难通过吞吐异常来调试不一致的状态。

请务必记住,一旦引发意外异常,您的应用程序处于未定义状态。问题请求可能永远无法完成,并且您的应用永远不会重新启动。或者其他任何奇怪的事情都可能发生。 (这是一个数据库问题?文件系统?损坏的内存?)

这些类型的情况难以置信地诊断,更不用说调试。它更安全,而且可以更好地快速失败,崩溃并重新启动服务器。是的,任何碰巧连接的客户都会被切断,但他们只需简单地重试即可。

如果您担心可用性,请使用cluster module,以便运行多个(通常为多个CPU核心)服务器进程,并且一次崩溃不会导致整个站点停止运行。

+1

这是一个很好的解释。但有一点我仍然不清楚。 '重要的是要记住,一旦抛出意外的异常,你的应用程序处于未定义的状态。问题请求可能永远不会完成,并且您的应用程序永远不会重新启动。这听起来好像我不应该打电话应用程序。关();在过程'退出'。真正? – lostintranslation

+0

在''process'' exit'处理程序中调用'app.close()'是毫无意义的:[docs say](http://nodejs.org/api/process.html#process_event_exit)*“主事件循环将会在'exit'回调完成后不再运行。“*换句话说,'exit'事件告诉你程序**将在你的函数返回后结束。由于没有下一个勾号,关闭网络监听器毫无意义;接受传入连接的代码永远不会有机会运行。 – josh3736

+0

真棒,谢谢! – lostintranslation

5

NodeJS在不期望发生任何事情时会关闭;当http服务器正在等待连接节点保持运行时。

server.close([callback])

停止接受新连接的服务器,并保持现有 连接。此功能是异步的,当所有连接都结束并且服务器发出事件时,服务器终于关闭了。 事件。或者,您可以传递回调来侦听事件的close 事件。

执行此操作后,服务器将继续运行,直到最后一次连接完成,然后正常关机。

如果您不想等待连接终止,则可以在剩余的连接上使用socket.end()socket.destroy()

http://nodejs.org/api/net.html


process.on('exit', function() { 
    console.log('About to exit, waiting for remaining connections to complete'); 
    app.close(); 
}); 

当节点存在并没有真正告诉节点退出此功能应该运行。这里是你可以结束你的过程,但它会无法正常结束的一种方法:

process.exit([code])

结束与指定代码的过程。如果省略,退出使用 '成功'代码0

要与“失败”代码退出:

process.exit(1);被执行节点应该看到退出代码 作为1壳。

http://nodejs.org/api/process.html


我希望这有助于!