web-dev-qa-db-ja.com

ノードjs ECONNRESET

チャットWebアプリケーション用にsocket.ioを使用してExpress jsアプリケーションを実行していますが、24時間に5回程度ランダムに次のエラーが発生します。ノードプロセスは永久にラップされ、すぐに再起動します。

問題は、expressを再起動してもユーザーが自分の部屋から追い出され、誰もそれを望んでいないことです。

WebサーバーはHAProxyによってプロキシされています。 WebSocketおよびFlashSocketトランスポートを使用するだけで、ソケットの安定性の問題はありません。意図的にこれを再現することはできません。

これはノードv0.10.11のエラーです。

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: read ECONNRESET     //alternatively it s a 'write'
    at errnoException (net.js:900:11)
    at TCP.onread (net.js:555:19)
error: Forever detected script exited with code: 8
error: Forever restarting script for 2 time

編集(2013年7月22日)

Socket.ioクライアントエラーハンドラとキャッチされていない例外ハンドラの両方を追加しました。これはエラーをキャッチしているようです。

process.on('uncaughtException', function (err) {
  console.error(err.stack);
  console.log("Node NOT Exiting...");
});

だから私はそれがsocket.ioの問題ではなく、私がしている別のサーバーへのhttpリクエストかmysql/redis接続だと思う。問題は、エラースタックがコードの問題の特定に役立たないことです。ログ出力はここにあります:

Error: read ECONNRESET
    at errnoException (net.js:900:11)
    at TCP.onread (net.js:555:19)

これが何を引き起こしているのか、どうすればわかりますか?どのように私はエラーからもっと抜け出すことができますか?

わかりました、それほど冗長ではありませんが、ここに "longjohn"の付いたスタックトレースがあります。

Exception caught: Error ECONNRESET
{ [Error: read ECONNRESET]
  code: 'ECONNRESET',
  errno: 'ECONNRESET',
  syscall: 'read',
  __cached_trace__:
   [ { receiver: [Object],
       fun: [Function: errnoException],
       pos: 22930 },
     { receiver: [Object], fun: [Function: onread], pos: 14545 },
     {},
     { receiver: [Object],
       fun: [Function: fireErrorCallbacks],
       pos: 11672 },
     { receiver: [Object], fun: [Function], pos: 12329 },
     { receiver: [Object], fun: [Function: onread], pos: 14536 } ],
  __previous__:
   { [Error]
     id: 1061835,
     location: 'fireErrorCallbacks (net.js:439)',
     __location__: 'process.nextTick',
     __previous__: null,
     __trace_count__: 1,
     __cached_trace__: [ [Object], [Object], [Object] ] } }

ここで私はフラッシュソケットポリシーファイルを提供します:

net = require("net")
net.createServer( (socket) =>
  socket.write("<?xml version=\"1.0\"?>\n")
  socket.write("<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n")
  socket.write("<cross-domain-policy>\n")
  socket.write("<allow-access-from domain=\"*\" to-ports=\"*\"/>\n")
  socket.write("</cross-domain-policy>\n")
  socket.end()
).listen(843)

これが原因でしょうか。

237
Samson

フラッシュポリシーファイルを提供するために私が持っていた簡単なtcpサーバはこれを引き起こしていました。ハンドラを使ってエラーをキャッチできます。

# serving the flash policy file
net = require("net")

net.createServer((socket) =>
  //just added
  socket.on("error", (err) =>
    console.log("Caught flash policy server socket error: ")
    console.log(err.stack)
  )

  socket.write("<?xml version=\"1.0\"?>\n")
  socket.write("<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n")
  socket.write("<cross-domain-policy>\n")
  socket.write("<allow-access-from domain=\"*\" to-ports=\"*\"/>\n")
  socket.write("</cross-domain-policy>\n")
  socket.end()
).listen(843)
33
Samson

あなたはすでにそれを推測しているかもしれません:それは接続エラーです。

"ECONNRESET"はTCP会話の反対側が突然接続の終わりを閉じたことを意味します。これはおそらく、1つ以上のアプリケーションプロトコルエラーが原因です。あなたはそれが何かについて不平を言うかどうか見るためにAPIサーバーログを見ることができます。

しかし、エラーをチェックして潜在的に問題をデバッグする方法も探しているので、" NodeJSでソケットハングアップエラーをデバッグする方法? "を見てください。同様の質問に関連してstackoverflowで投稿されました。

開発のための迅速で汚い解決策

longjohn を使用すると、非同期操作を含む長いスタックトレースが表示されます。

清潔で正しい解決策 :技術的には、ノード内で あなたが'error'イベントを発行し、それを聞いている人がいないときはいつでも、 がスローされます。投げないようにするには、リスナーをその上に置いて自分で処理します。そうすれば、エラーをより多くの情報と共に記録することができます。

呼び出しのグループに対して1つのリスナーを持つには、 domains を使用し、実行時に他のエラーを検出することもできます。 http(Server/Client)に関連する各非同期操作がコードの他の部分と比較して異なる domain contextにあることを確認してください。ドメインは自動的にerrorイベントをリッスンし、それを独自のハンドラに伝播します。だからあなたはそのハンドラを聞いてエラーデータを取得するだけです。 あなたは無料でより多くの情報も得ます。

EDIT(2013-07-22)

私が上で書いたように:

"ECONNRESET"はTCP会話の反対側が突然接続の終わりを閉じたことを意味します。これはおそらく、1つ以上のアプリケーションプロトコルエラーが原因です。あなたはそれが何かについて不平を言うかどうか見るためにAPIサーバーログを見ることができます。

また、ランダムな時間に相手側が過負荷になり、結果として接続が切断されることもあります。その場合は、接続している内容によって異なります。

しかし、確かなことが1つあります。TCP接続で読み取りエラーが発生したために、例外が発生したことを示しています。あなたはそれを確認するためにあなたの編集で投稿したエラーコードを見ることによってそれを見ることができます。

216
e-sushi

Nodeのアップグレード後にアプリがエラーを起こし始めるという同様の問題がありました。私はこれがNode release v0.9.10 this itemまでさかのぼることができると思います。

  • net:ECONNRESETを抑制しない(Ben Noordhuis)

以前のバージョンでは、クライアントからの中断によってエラーが発生しませんでした。クライアントからの接続が切断されると、NodeにエラーECONNRESETがスローされます。私はこれがNodeの機能を意図していると信じているので、(少なくとも私にとっては)修正はエラーを処理することでした。私はそれをnet.socketハンドラで処理しますが。

あなたはこれを実証することができます:

単純なソケットサーバを作り、Node v0.9.9とv0.9.10を入手してください。

require('net')
    .createServer( function(socket) 
    {
           // no nothing
    })
    .listen(21, function()
     {
           console.log('Socket ON')
    })

V0.9.9を使用して起動してから、このサーバーへのFTP送信を試みます。 FTPとポート21を使用しているのは、Windows上にFTPクライアントがあるためだけですが、telnetクライアントは役に立ちません。

その後、クライアント側から接続を切断します。 (私はCtrl-Cをしているだけです)

Node v0.9.9を使用するとNO ERRORが表示され、Node v.0.9.10以降を使用するとERRORが表示されます。

プロダクションでは、v.0.10を使います。何か、それはまだエラーを与えます。繰り返しますが、これは意図的なものであり、解決策はコード内のエラーを処理することです。

26
John Williams

私は同じ問題に直面していましたが、私はそれを置くことによってそれを軽減しました:

server.timeout = 0;

server.listenの前。 serverは、ここではHTTPサーバーです。デフォルトのタイムアウトは APIドキュメント によると2分です。

14
Ashish Kaila

今日も同じ問題がありました。いくつかの調査の後、私はとても便利な --abort-on-uncaught-exception node.jsオプションを見つけました 。より冗長で有用なエラースタックトレースを提供するだけでなく、アプリケーションのクラッシュ時にコアファイルを節約して、さらなるデバッグを可能にします。

13
stainful

はい、あなたのポリシーファイルの提供は間違いなくクラッシュを引き起こす可能性があります。

繰り返しますが、コードに遅延を追加するだけです。

net.createServer( function(socket) 
{
  for(i=0; i<1000000000; i++);
  socket.write("<?xml version=\"1.0\"?>\n")
…

…そしてtelnetを使ってポートに接続します。遅延時間が経過する前にtelnetを切断すると、socket.writeがエラーをスローしたときにクラッシュ(キャッチされない例外)が発生します。

ここでのクラッシュを避けるために、ソケットを読み書きする前にエラーハンドラを追加するだけです。

net.createServer( function(socket) 
{
  for(i=0; i<1000000000; i++);
  socket.on('error', function() { console.log("error"); });
  socket.write("<?xml version=\"1.0\"?>\n")

上記の接続解除を試すと、クラッシュではなくログメッセージが表示されるだけです。

そして完了したら、遅延を削除することを忘れないでください。

7

サーバー間の通信があり、server.maxConnectionsを非常に低い値に設定している場合も考えられます。

ノードのコアlib net.js ではclientHandle.close()が呼び出され、これもエラーECONNRESETを引き起こします。

if (self.maxConnections && self._connections >= self.maxConnections) {
  clientHandle.close(); // causes ECONNRESET on the other end
  return;
}
6
happy_marmoset

また、開発中にECONNRESETエラーが発生しました。解決方法は、nodemonを使用してサーバーを起動するnotです。サーバーを起動するには"node server.js"を使用するだけで問題が解決しました。

それは奇妙です、しかしそれは私のために働きました、今私は二度とECONNRESETエラーを見ることはありません。

4
Andrew Lam

私はこの問題を解決しました:

  • 無線LAN /イーサネット接続をオフにしてオンにします。
  • Npmを更新するために端末にnpm updateと入力しました。
  • セッションからログアウトして再度ログインしようとしました

その後、私は同じnpmコマンドを試してみましたが、良いことはうまくいきました。それがそれほど単純かどうかわからなかった。

CENTOS 7を使用しています

1
muhammad tayyab

別のネットワークに接続することで問題を解決しました 。それが考えられる問題の1つです。

前述のように、 _ econnreset _ はTCP会話が突然接続の終わりを閉じたことを意味します。

インターネットに接続しているため、一部のサーバーへの接続がブロックされている可能性があります。私の場合は、mLab(MongoDBデータベースをホストするクラウドデータベースサービス)に接続しようとしていました。そして私のISPはそれをブロックしています。

1
Yousef

私もこのエラーを抱えていて、何日ものデバッグと分析の後にそれを解決することができました:

私の解決策

私にとってはVirtualBox(Docker用)が問題でした。 VMでポート転送を設定しましたが、転送されたポートでのみエラーが発生しました。

一般的な結論

以下の観察は私が投資しなければならなかった仕事のあなたの日数を節約するかもしれません:

  • 私にとっては、この問題は1つのポート上のlocalhostからlocalhostへの接続でのみ発生しました。 - >これらの定数を変更することで問題が解決します。
  • 私にとっては、問題は私のマシンでのみ発生しました - >他の人に試してみてください。
  • 私にとっては、問題はしばらくしてから発生し、確実に再現できなかった
  • 私の問題は、どのノードやexpress(debug-)ツールでも調べることができませんでした。 - >これで時間を無駄にしないで

- > VM、ファイアウォールなどのように何かがあなたのネットワークでめちゃくちゃになっている(設定)場合、これがおそらく問題の原因です。

1
Waog

これらのオプションをsocket.ioに追加してみてください。

const options = { transports: ['websocket'], pingTimeout: 3000, pingInterval: 5000 };

これがお役に立てば幸いです。

0
sol404