http.createServer中的'uncaughtException'

时间:2012-04-04 20:01:13

标签: node.js

我想在错误中请求res.end('server error')。我的代码:

http.createServer(function(req,res){
  process.on('uncaughtException', function() {
    res.end('server error')
  })
  handlers(req,res)
}).listen(1337)

我的决定出了什么问题?

2 个答案:

答案 0 :(得分:4)

你会收到如下错误/警告:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:389:29)
    at Server.<anonymous> (/Users/taf2/work/phonetrac/services/ctm-pool/foo.js:2:11)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1572:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:91:29)
    at Socket.ondata (http.js:1468:22)
    at TCP.onread (net.js:374:27)

我将假设您正在执行上述操作,因为您注意到当您开始捕获uncaughtException时,客户端连接不再被关闭,因此,如果出现错误,客户端连接将永远不会被释放。例如,如果您将node.js端点作为客户端请求嵌入脚本标记中,例如

<script src="http://127.0.0.1:1337/yourendpoint.js"></script>

这会挂起您服务的消费者......希望您使用异步技术嵌入脚本......

无论如何,只要你处理释放事件监听器,使用你的技术来处理错误就可以了。

function handleError(err) {
  console.error("Caught exception:", err, err.stack);
  this.end();
  this.emit("cleanup");
}

require('http').createServer(function(req, res) {
  var errorHandler = handleError.bind(res)
  process.on("uncaughtException", errorHandler);
  res.on("cleanup", function() { process.removeListener("uncaughtException", errorHandler); });

  this.is.an.error;

  res.end();
  res.emit("cleanup");
}).listen(1337);

尝试一下,我们没有泄漏,我们的错误得到处理,连接关闭,让我们的客户可以继续前进到下一个错误:

ab -n 100 -c 10 http://127.0.0.1:1337/

但是,如果您的服务器执行如下所示的任何复杂操作,此解决方案将在并发性下分解:

function handleError(err) {
  console.error("Caught exception:", err, err.stack);
  this.end();
  this.emit("error:cleanup");
}

require('http').createServer(function(req, res) {
  var errorHandler = handleError.bind(res)
  process.on("uncaughtException", errorHandler);
  res.on("error:cleanup", function() { process.removeListener("uncaughtException", errorHandler); });

  setTimeout(function() {
    this.is.an.error;
    res.end();
    res.emit("cleanup");
  },1000);

}).listen(1337);

这里的问题是uncaughtException将被触发所有错误,它们将重叠。这意味着捕获像这样的全局错误最好只有一个process.on(“uncaughtException”处理程序。

相反,在上述情况下,您需要:

  • 有一个孤立的try {} catch {}块 - 这可能很难做对。
  • 允许异常进行未捕获并使进程崩溃,使用monit或类似的东西重新启动进程。
  • 您可以尝试使用setInternval清理函数来过滤掉已关闭的连接。

以下是使用setInterval。

var connectionIndex = 0;
var connections = [];

function handleError(err) {
  console.error("Caught exception:", err, err.stack);
  connections.forEach(function(conn) {
    conn.end();
  });
}

var server = require('http').createServer(function(req, res) {
  connections.push(res.connection);

  setTimeout(function() {
    this.is.an.error;
    res.end();
  },100);

});

setInterval(function() {
  console.log("conn check: %d", connections.length);
  connections = connections.filter(function(conn) {
    return !conn.destroyed;
  });
},1000);

process.on("uncaughtException", handleError);

server.listen(1337);

我有点像最后一个解决方案,但我确信它可能会有一些优势,所以使用第二个解决方案有一个监控服务来重启你的服务器可能是最好的。

答案 1 :(得分:-1)

process.on("uncaughtException", handleError);