2

本来想问一个问题,关于如何基于Node.js创建robuts web server。但是,这可能是一个非常大且模棱两可的问题。因此,我将其分解为创建 robuts Web 服务器时所面临的小而具体的问题或挑战。

所以,我面临的挑战之一是如何在 Node.js 中捕获所有未处理的错误?我想这样做是因为我不希望任何未处理的错误阻止 Node.js 运行,从而导致 Web 服务器停机。

想到的解决方案是将服务器运行的代码块放在 try-catch 块中,以捕获所有未处理的错误。但是,如果异步方法发生任何错误,这将不起作用。例如,我的 Web 服务器可能如下代码所示:

var fs = require('fs');
var http = require('http');

try {

    // Here is my main web server, it could happen errors by adding
    // more and more modules and functionalities to my server.
    // I need to catch all unhandled errors to prevent server from crashing
    // So, I put my whole server running in a try-catch block, but any error from
    // an async method could not be caught!
    http.createServer(function(req, res) {
        throw Error("An unhandled error happens!");
    }).listen(1234);

}catch (e){
    console.log("An unhandled error caught!")
}

console.log('Server is listening to port 1234');

那么,我是否处于正确的错误处理方向以确保服务器不会停止?还是有其他机制可以使服务器从错误中恢复?

4

3 回答 3

4

您需要使用

一个包含所有服务器的全局域和每个请求一个域。如果您在初始化期间遇到错误,全局域将捕获该错误,然后您可以记录它,执行一些清理任务并终止服务器。如果您从请求中收到错误,请以最高优先级记录它并继续为其他请求提供服务。这就是 node.js 希望我们编写健壮的 Web 服务器的方式。

主要问题是尝试尽可能优雅地关闭。优雅退出意味着当您需要终止服务器(从 ctrl-c 或 sigint 或错误或其他)而不是执行简单process.exit(1)操作时,您必须清理资源,例如关闭数据库连接、关闭文件、通知某人等。您不能使用process.on("exit", ...),因为当调用处理程序时,事件循环不起作用并且您无法执行异步任务。

另外,如果您使用工作人员,当服务器需要关闭时,您如何优雅地关闭它们?

你如何处理快速错误?

所有这些东西似乎都很难实现以始终保证正常关闭。这就是我做node-grace的原因。

于 2013-03-29T13:42:13.417 回答
2

在回调函数中使用 try/catch:

var fs = require('fs');
var http = require('http');

try {
    http.createServer(function(req, res) {
        try{
            // some code trowing erors
        }catch(e){
             console.log("error: " + e);
        }
}).listen(1234);

}catch (e){
    console.log("An unhandled error caught!")
}

console.log('Server is listening to port 1234');

为什么会这样?异步 http 回调不会与设置 http 服务器回调函数的代码在同一滴答声中运行(此外,每次服务器收到请求时都会调用该函数)。试试你自己:

 try{
      throw Error("An unhandled error happens!");
 }catch(e){
     console.log(e)
 }

和:

 try{
     process.nextTick(function(){
        throw Error("An unhandled error happens!")
     });
 }
 catch(e){
     console.log(e)
 }
于 2013-03-29T12:20:37.677 回答
1

如果您可以选择使用 Express,我建议您使用它而不是相当低级的http模块。使用 Express,您可以很好地处理错误:

var express = require('express');
var app     = express();

app.get('/', function(req, res) {
  throw Error("An unhandled error happens!");
});

app.use(function(err, req, res, next) {
  console.log('error', err);
  res.send(500); // send a proper HTTP 500 message back to the client
});

app.listen(1234);

console.log('Server is listening to port 1234');

不然看看Node的domain模块

于 2013-03-29T11:57:23.210 回答