Node js ECONNRESET

Jeg kjører en Express js applikasjon med socket.io for en chat webapp og jeg får følgende feil tilfeldig rundt 5 ganger under 24h. Nodeprosessen er pakket inn for alltid, og den starter på nytt seg selv umiddelbart.

Problemet er at omstart av ekspress sparker brukerne mine ut av rommene sine og ingen ønsker det.

Webserveren er proxy av HAProxy. Det er ingen problemer med socket-stabilitet, bare ved bruk av websockets og flashsockets-transporter. Jeg kan ikke reprodusere dette med vilje.

Dette er feilen med 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)

Lagt til både socket.io client error handler og uncaught exception handler. Ser ut til at denne fanger opp feilen:

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

Så jeg mistenker at det ikke er et socket.io-problem, men en http-forespørsel til en annen server som jeg gjør eller en mysql / redis-tilkobling. Problemet er at feilstakken ikke hjelper meg med å identifisere kodeproblemet mitt. Her er loggutgangen:

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

Hvordan vet jeg hva som forårsaker dette? Hvordan får jeg mer ut av feilen?

Ok, ikke veldig ordrik, men her er stacktrace med " 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] ] } }

Her serverer jeg flash socket-policyfilen:

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)

Kan dette være årsaken?

Du har kanskje gjettet det allerede: det er en tilkoblingsfeil.

*ECONNRESET betyr at den andre siden av TCP-samtalen brått avsluttet forbindelsen. Dette skyldes sannsynligvis en eller flere applikasjonsprotokollfeil. Du kan se på API-serverloggene for å se om den klager på noe.

Men siden du også leter etter en måte å sjekke feilen og potensielt feilsøke problemet, bør du ta en titt på &"Hvordan feilsøke en socket hang up error i NodeJS?" som ble lagt ut på stackoverflow i forhold til et lignende spørsmål.

Rask og skitten løsning for utvikling:

Bruk longjohn, du får lange stakkspor som vil inneholde async-operasjonene.

Ren og korrekt løsning: Teknisk sett, i node, når du sender ut en &#39;error&#39;-hendelse og ingen lytter til den, vil den kaste. For å få den til å ikke kaste, sett en lytter på den og håndter den selv. På den måten kan du logge feilen med mer informasjon.

For å ha en lytter for en gruppe anrop kan du bruke domains og også fange opp andre feil under kjøring. Forsikre deg om at hver asynkroniseringsoperasjon relatert til http (Server / Client) er i en annen domene kontekst sammenlignet med de andre delene av koden, vil domenet automatisk lytte til feil hendelser og vil forplante den til sin egen handler. Så du lytter bare til den behandleren og får feildataene. Du får også mer informasjon gratis.

REDIGER (2013-07-22)

Som jeg skrev ovenfor:

"ECONNRESET" betyr at den andre siden av TCP-samtalen brått stengte sin ende av forbindelsen. Dette skyldes sannsynligvis en eller flere applikasjonsprotokollfeil. Du kan se på API-serverloggene for å se om den klager på noe.

Hva kan også være tilfelle: på tilfeldige tidspunkter er den andre siden overbelastet og dreper ganske enkelt forbindelsen som et resultat. Hvis det er tilfelle, avhenger det av hva du kobler til nøyaktig ...

Men en ting er sikkert: du har faktisk en lesefeil på TCP-tilkoblingen din som forårsaker unntaket. Du kan se det ved å se på feilkoden du la ut i redigeringen din, som bekrefter det.

Kommentarer (4)
Løsning

En enkel tcp-server jeg hadde for å betjene flash-policyfilen forårsaket dette. Jeg kan nå fange feilen ved hjelp av en handler:

# 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("\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.end()
).listen(843)
Kommentarer (5)

Jeg hadde et lignende problem der apper begynte å feile etter en oppgradering av Node. Jeg tror dette kan spores tilbake til Node release v0.9.10 dette elementet:

  • netto: ikke undertrykk ECONNRESET (Ben Noordhuis)

Tidligere versjoner ville ikke gi feil ved avbrudd fra klienten. Et brudd i forbindelsen fra klienten kaster feilen ECONNRESET i Node. Jeg tror dette er tiltenkt funksjonalitet for Node, så løsningen (i det minste for meg) var å håndtere feilen, som jeg tror du gjorde i unCaught unntak. Selv om jeg håndtere det i net.socket handler.

Du kan demonstrere dette:

Lag en enkel socket-server og få Node v0.9.9 og v0.9.10.

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

Start den opp med v0.9.9 og prøv deretter å FTP til denne serveren. Jeg bruker bare FTP og port 21 fordi jeg bruker Windows og har en FTP-klient, men ingen telnet-klient tilgjengelig.

Så fra klientsiden er det bare å bryte forbindelsen. (Jeg gjør bare Ctrl-C)

Du bør se NO ERROR når du bruker Node v0.9.9, og ERROR når du bruker Node v.0.9.10 og nyere.

I produksjon bruker jeg v.0.10. noe, og det gir fortsatt feilen. Igjen, jeg tror dette er ment, og løsningen er å håndtere feilen i koden din.

Kommentarer (2)