http.createServer中的'uncaughtException'

如果错误,我想请求res.end('服务器错误')。 我的代码:

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

我的决定有什么问题?

你会得到这样的错误/警告:

 (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时,客户端连接不再被closures,所以在发生错误时客户端连接永远不会被释放。 例如,如果您将node.js端点作为客户端请求embedded到脚本标记中,例如

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

这将挂起你的服务的消费者…希望你用asynchronous技术embedded你的脚本…

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

 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); 

试试看,我们没有泄漏,我们的错误得到处理,连接closures,让我们的客户免费移动到下一个错误:

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

但是,如果您的服务器执行以下任何复杂操作,则此解决scheme将在并发下崩溃:

 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”处理程序。

相反在上面的情况下,你会想要:

  • 有一个孤立的尝试{} catch {}块 – 这可能是很难得到正确的。
  • 允许exception未被捕获并崩溃的过程中,使用monit或类似的东西重新启动过程。
  • 你可以尝试一个具有setInternval清理函数的数组来过滤掉closures的连接。

以下是使用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); 

我有点像最后一个解决scheme,但我敢肯定,可能有边缘咬,所以使用第二个解决scheme有一个监控服务来重新启动您的服务器可能是最好的。

 process.on("uncaughtException", handleError);