チャット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)
これが原因でしょうか。
フラッシュポリシーファイルを提供するために私が持っていた簡単な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)
あなたはすでにそれを推測しているかもしれません:それは接続エラーです。
"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接続で読み取りエラーが発生したために、例外が発生したことを示しています。あなたはそれを確認するためにあなたの編集で投稿したエラーコードを見ることによってそれを見ることができます。
Nodeのアップグレード後にアプリがエラーを起こし始めるという同様の問題がありました。私はこれがNode release v0.9.10 this itemまでさかのぼることができると思います。
以前のバージョンでは、クライアントからの中断によってエラーが発生しませんでした。クライアントからの接続が切断されると、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を使います。何か、それはまだエラーを与えます。繰り返しますが、これは意図的なものであり、解決策はコード内のエラーを処理することです。
私は同じ問題に直面していましたが、私はそれを置くことによってそれを軽減しました:
server.timeout = 0;
server.listen
の前。 server
は、ここではHTTPサーバーです。デフォルトのタイムアウトは APIドキュメント によると2分です。
今日も同じ問題がありました。いくつかの調査の後、私はとても便利な --abort-on-uncaught-exception
node.jsオプションを見つけました 。より冗長で有用なエラースタックトレースを提供するだけでなく、アプリケーションのクラッシュ時にコアファイルを節約して、さらなるデバッグを可能にします。
はい、あなたのポリシーファイルの提供は間違いなくクラッシュを引き起こす可能性があります。
繰り返しますが、コードに遅延を追加するだけです。
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")
上記の接続解除を試すと、クラッシュではなくログメッセージが表示されるだけです。
そして完了したら、遅延を削除することを忘れないでください。
サーバー間の通信があり、server.maxConnections
を非常に低い値に設定している場合も考えられます。
ノードのコアlib net.js ではclientHandle.close()
が呼び出され、これもエラーECONNRESETを引き起こします。
if (self.maxConnections && self._connections >= self.maxConnections) {
clientHandle.close(); // causes ECONNRESET on the other end
return;
}
また、開発中にECONNRESETエラーが発生しました。解決方法は、nodemonを使用してサーバーを起動するnotです。サーバーを起動するには"node server.js"
を使用するだけで問題が解決しました。
それは奇妙です、しかしそれは私のために働きました、今私は二度とECONNRESETエラーを見ることはありません。
私はこの問題を解決しました:
npm update
と入力しました。その後、私は同じnpmコマンドを試してみましたが、良いことはうまくいきました。それがそれほど単純かどうかわからなかった。
CENTOS 7を使用しています
別のネットワークに接続することで問題を解決しました 。それが考えられる問題の1つです。
前述のように、 _ econnreset _ はTCP会話が突然接続の終わりを閉じたことを意味します。
インターネットに接続しているため、一部のサーバーへの接続がブロックされている可能性があります。私の場合は、mLab(MongoDBデータベースをホストするクラウドデータベースサービス)に接続しようとしていました。そして私のISPはそれをブロックしています。
私もこのエラーを抱えていて、何日ものデバッグと分析の後にそれを解決することができました:
私にとってはVirtualBox(Docker用)が問題でした。 VMでポート転送を設定しましたが、転送されたポートでのみエラーが発生しました。
以下の観察は私が投資しなければならなかった仕事のあなたの日数を節約するかもしれません:
- > VM、ファイアウォールなどのように何かがあなたのネットワークでめちゃくちゃになっている(設定)場合、これがおそらく問題の原因です。
これらのオプションをsocket.ioに追加してみてください。
const options = { transports: ['websocket'], pingTimeout: 3000, pingInterval: 5000 };
これがお役に立てば幸いです。