2

エラーの場合はリクエストで res.end('server error') したいです。私のコード:

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

私の決定の何が問題なのですか?

4

2 に答える 2

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" ハンドラーを 1 つだけ持つのが最善であることを意味します。

上記の状況では、代わりに次のことを行います。

  • 分離した 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);

私は最後のソリューションが好きですが、それに食い込むエッジがあるかもしれないと確信しているので、2番目のソリューションを使用して監視サービスを使用してサーバーを再起動するのがおそらく最善です.

于 2012-05-30T02:37:37.220 に答える
-1
process.on("uncaughtException", handleError);
于 2012-09-18T00:09:40.233 に答える