421 Stimmen

Wie behebe ich den Fehler ECONNRESET in Node.js?

Ich betreibe eine Express.js-Anwendung, die Socket.io für eine Chat-Webanwendung verwendet, und ich erhalte den folgenden Fehler sporadisch etwa 5 Mal innerhalb von 24 Stunden. Der Node-Prozess ist in forever eingebunden und startet sich sofort neu.

Das Problem ist, dass das Neustarten von Express meine Benutzer aus ihren Räumen wirft und das möchte niemand.

Der Webserver wird von HAProxy proxied. Es gibt keine Probleme mit der Socket-Stabilität, es werden nur Websockets und Flashsockets-Transports verwendet. Ich kann diesen Fehler nicht absichtlich reproduzieren.

Das ist der Fehler mit Node 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

EDIT (2013-07-22)

Habe sowohl den Fehlerhandler für den socket.io-Client als auch den unerfassten Ausnahme-Handler hinzugefügt. Es scheint, dass dieser den Fehler erfasst:

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

Ich vermute also, dass es kein Socket.io-Problem ist, sondern eine HTTP-Anfrage an einen anderen Server, die ich mache, oder eine MySQL/Redis-Verbindung. Das Problem ist, dass der Fehler-Stack mir nicht hilft, meinen Codefehler zu identifizieren. Hier ist die Protokollausgabe:

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

Wie kann ich herausfinden, was das verursacht? Wie bekomme ich mehr Informationen aus dem Fehler?

Okay, nicht sehr ausführlich, aber hier ist der Stacktrace mit 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] ] } }

Hier bediene ich die Flash-Socket-Richtliniendatei:

    net = require("net")
    net.createServer( (socket) =>
      socket.write("\n")
      socket.write("\n")
      socket.write("\n")
      socket.write("\n")
      socket.write("\n")
      socket.end()
    ).listen(843)

Kann das die Ursache sein?

374voto

e-sushi Punkte 12963

Sie haben es vielleicht schon erraten: es handelt sich um einen Verbindungsfehler.

"ECONNRESET" bedeutet, dass die andere Seite des TCP-Gesprächs ihre Verbindung abrupt geschlossen hat. Dies liegt höchstwahrscheinlich an einem oder mehreren Fehlern im Anwendungsprotokoll. Sie könnten die API-Serverprotokolle überprüfen, um zu sehen, ob etwas darüber beschwert.

Aber da Sie auch nach einer Möglichkeit suchen, den Fehler zu überprüfen und möglicherweise das Problem zu debuggen, sollten Sie sich "How to debug a socket hang up error in NodeJS?" anschauen, das auf stackoverflow in Bezug auf eine ähnliche Frage veröffentlicht wurde.

Schnelle und einfache Lösung für die Entwicklung:

Verwenden Sie longjohn, um lange Stapelverfolgungen zu erhalten, die die asynchronen Vorgänge enthalten werden.

Saubere und korrekte Lösung: Technisch gesehen, wird in Node jedes Mal, wenn ein 'error'-Ereignis ausgelöst wird und niemand darauf hört, eine Ausnahme geworfen. Um das Werfen zu verhindern, setzen Sie einen Zuhörer darauf und behandeln Sie es selbst. Auf diese Weise können Sie den Fehler mit mehr Informationen protokollieren.

Um einen Zuhörer für eine Gruppe von Aufrufen zu haben, können Sie Domains verwenden und auch andere Fehler zur Laufzeit erfassen. Stellen Sie sicher, dass jeder asynchrone Vorgang im Zusammenhang mit http(Server/Client) in einem anderen Domain-Kontext im Vergleich zu anderen Teilen des Codes steht, das Domain wird automatisch auf die error-Ereignisse hören und es an seinen eigenen Handler weiterleiten. Sie hören also nur auf diesen Handler und erhalten die Fehlerdaten. Sie erhalten auch mehr Informationen kostenlos.

EDIT (2013-07-22)

Wie ich oben geschrieben habe:

"ECONNRESET" bedeutet, dass die andere Seite des TCP-Gesprächs ihre Verbindung abrupt geschlossen hat. Dies liegt höchstwahrscheinlich an einem oder mehreren Fehlern im Anwendungsprotokoll. Sie könnten die API-Serverprotokolle überprüfen, um zu sehen, ob etwas darüber beschwert.

Was auch der Fall sein könnte: zu zufälligen Zeiten ist die andere Seite überlastet und beendet einfach die Verbindung als Ergebnis. Falls das zutrifft, hängt davon ab, mit was genau Sie verbunden sind…

Aber eins ist sicher: Sie haben tatsächlich einen Lesefehler in Ihrer TCP-Verbindung, der die Ausnahme verursacht. Dies können Sie anhand des von Ihnen in Ihrem Edit geposteten Fehlercodes sehen, der dies bestätigt.

58voto

Samson Punkte 2751

Ein einfacher TCP-Server, den ich hatte, um die Flash-Richtliniendatei zu bedienen, verursachte dies. Jetzt kann ich den Fehler mithilfe eines Handlers abfangen:

# Bereitstellung der Flash-Richtliniendatei
net = require("net")

net.createServer((socket) =>
  // gerade hinzugefügt
  socket.on("error", (err) =>
    console.log("Erkannter Fehler im Flash-Richtliniendatei-Server-Socket: ")
    console.log(err.stack)
  )

  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.end()
).listen(843)

37voto

John Williams Punkte 10750

Ich hatte ein ähnliches Problem, bei dem Apps nach einem Upgrade von Node plötzlich Fehlermeldungen generierten. Ich glaube, dass dies auf das Node-Release v0.9.10 zurückzuführen ist, genauer gesagt auf dieses Element:

  • net: unterdrücke ECONNRESET nicht (Ben Noordhuis)

Frühere Versionen haben keine Fehler bei Unterbrechungen des Clients generiert. Ein Verbindungsabbruch seitens des Clients löst den Fehler ECONNRESET in Node aus. Ich glaube, dass dies beabsichtigtes Verhalten für Node ist, daher war die Lösung (zumindest für mich), mit dem Fehler umzugehen, was du wahrscheinlich bereits bei unbehandelten Ausnahmen gemacht hast. Ich behandle es jedoch im net.socket-Handler.

Du kannst das so demonstrieren:

Erstelle einen einfachen Socket-Server und lade Node v0.9.9 und v0.9.10 herunter.

require('net')
    .createServer( function(socket) 
    {
           // mache nichts
    })
    .listen(21, function()
     {
           console.log('Socket AN')
    })

Führe es mit v0.9.9 aus und versuche dann, eine FTP-Verbindung zu diesem Server herzustellen. Ich verwende FTP und Port 21 nur, weil ich Windows benutze und einen FTP-Client, aber keinen Telnet-Client zur Hand habe.

Dann auf der Client-Seite einfach die Verbindung unterbrechen. (Ich benutze einfach Strg-C)

Du solltest KEINEN FEHLER sehen, wenn du Node v0.9.9 verwendest, und EINEN FEHLER, wenn du Node v.0.9.10 und höher verwendest.

In der Produktion verwende ich etwas wie v.0.10 und erhalte immer noch den Fehler. Noch einmal, ich glaube, dass dies beabsichtigt ist und die Lösung darin besteht, mit dem Fehler in deinem Code umzugehen.

24voto

stainful Punkte 26

Ich hatte heute dasselbe Problem. Nach einiger Recherche habe ich eine sehr nützliche --abort-on-uncaught-exception Node.js-Option gefunden. Diese bietet nicht nur eine viel ausführlichere und nützlichere Fehler-Stack-Trace, sondern speichert auch eine Kerneldatei beim Anwendungsabsturz zur weiteren Fehlerbehebung.

19voto

Andrew Lam Punkte 3426

Während meiner Entwicklung erhalte ich auch den ECONNRESET-Fehler, den ich löse, indem ich nicht nodemon benutze, um meinen Server zu starten, sondern einfach "node server.js" verwende, um meinen Server zu starten und mein Problem zu beheben.

Es ist merkwürdig, aber es hat bei mir funktioniert, jetzt sehe ich den ECONNRESET-Fehler nie wieder.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X