web-dev-qa-db-fra.com

Nœud js ECONNRESET

Je lance une application Express js avec socket.io pour une discussion webapp et j'ai l'erreur suivante au hasard environ 5 fois pendant 24h Le processus de noeud est encapsulé pour toujours et redémarre lui-même immédiatement.

Le problème est que le redémarrage de Express expulse mes utilisateurs de leurs salles et personne ne veut ça.

Le serveur Web est mandaté par HAProxy. Il n'y a pas de problèmes de stabilité de socket, juste en utilisant websockets et des transports flashsockets. Je ne peux pas reproduire cela exprès. 

C'est l'erreur avec le noeud 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)

Ajout du gestionnaire d'erreur client socket.io et du gestionnaire d'exception non capturé. Semble que celui-ci attrape l'erreur:

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

Donc, je soupçonne que ce n'est pas un problème de socket.io mais une requête http à un autre serveur que je fais ou une connexion mysql/redis Le problème est que la pile d'erreurs ne m'aide pas à identifier mon problème de code. Voici la sortie du journal: 

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

Comment puis-je savoir ce qui cause cela? Comment puis-je tirer le meilleur parti de l'erreur? 

Ok, pas très verbeux mais voici la pile avec "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] ] } }

Ici, je sers le fichier de politique de socket flash:

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)

Cela peut-il être la cause? 

223
Samson

Un simple serveur TCP que j'avais pour servir le fichier de politique flash était la cause Je peux maintenant attraper l'erreur en utilisant un gestionnaire:

# 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)
31
Samson

Vous l'avez peut-être déjà deviné: c'est une erreur de connexion. 

"ECONNRESET" signifie que l'autre côté de la conversation TCP a fermé brutalement sa fin de la connexion. Cela est probablement dû à une ou plusieurs erreurs de protocole d'application. Vous pouvez consulter les journaux du serveur d'API pour voir s'il se plaint de quelque chose.

Mais puisque vous cherchez également un moyen de vérifier l’erreur et potentiellement de déboguer le problème, vous devriez jeter un oeil à " Comment déboguer une erreur de raccrochage de socket dans NodeJS? " qui était posté à stackoverflow par rapport à une question similaire.

Solution rapide et sale pour le développement:

Utilisez longjohn , vous obtenez des traces de pile longues qui contiendront les opérations asynchrones.

Solution propre et correcte: Techniquement, dans le noeud, chaque fois que vous émettez un événement 'error' et que personne ne l'écoute, il lancera . Pour ne pas le jeter, placez un auditeur dessus et manipulez-le vous-même. De cette façon, vous pouvez enregistrer l'erreur avec plus d'informations.

Pour avoir un auditeur pour un groupe d'appels, vous pouvez utiliser -domaines et aussi détecter d'autres erreurs lors de l'exécution. Assurez-vous que chaque opération asynchrone liée à http (serveur/client) se trouve dans un contexte domain différent des autres parties du code, le domaine écoutera automatiquement les événements error et le transmettra à son propre gestionnaire. Vous n'écoutez donc que ce gestionnaire et obtenez les données d'erreur. Vous obtenez également plus d'informations gratuitement.

EDIT (2013-07-22)

Comme je l'ai écrit ci-dessus: 

"ECONNRESET" signifie que l'autre côté de la conversation TCP a fermé brutalement sa fin de la connexion. Cela est probablement dû à une ou plusieurs erreurs de protocole d'application. Vous pouvez consulter les journaux du serveur d'API pour voir s'il se plaint de quelque chose.

Ce qui pourrait également être le cas: à des moments aléatoires, l’autre côté est surchargé et tue simplement la connexion en conséquence. Si c'est le cas, cela dépend de ce à quoi vous vous connectez exactement…

Mais une chose est sûre: vous avez effectivement une erreur de lecture sur votre connexion TCP qui provoque l'exception. Vous pouvez voir cela en regardant le code d'erreur que vous avez posté dans votre édition, ce qui le confirme. 

209
e-sushi

J'ai eu un problème similaire: les applications ont commencé à afficher des erreurs après une mise à niveau de Node. Je pense que cela remonte à la publication du nœud v0.9.10:

  • net: ne pas supprimer ECONNRESET (Ben Noordhuis)

Les versions précédentes ne généraient pas d'erreur lors d'interruptions du client. Une interruption de la connexion du client génère l'erreur ECONNRESET dans Node. Je crois que cette fonctionnalité est destinée à Node. Le correctif (du moins pour moi) consistait donc à gérer l'erreur, ce que je pense que vous avez fait dans les exceptions non capturées. Bien que je le gère dans le gestionnaire net.socket.

Vous pouvez démontrer ceci:

Créez un serveur de socket simple et obtenez les nœuds v0.9.9 et v0.9.10.

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

Démarrez-le avec v0.9.9 puis essayez d'envoyer FTP sur ce serveur. J'utilise FTP et le port 21 uniquement parce que je suis sous Windows et que j'ai un client FTP, mais pas de client telnet. 

Ensuite, côté client, il suffit de rompre la connexion. (Je fais juste Ctrl-C)

NO ERROR lors de l’utilisation de Node v0.9.9 et ERROR lors de l’utilisation de Node v.0.9.10 et versions ultérieures.

En production, j'utilise v.0.10. quelque chose et il donne toujours l'erreur. Encore une fois, je pense que cela est prévu et que la solution consiste à gérer l'erreur dans votre code.

24
John Williams

Je faisais face au même problème mais je l'ai atténué en plaçant:

server.timeout = 0;

avant server.listen. server est un serveur HTTP ici. Le délai d'attente par défaut est de 2 minutes, conformément à la documentation API .

14
Ashish Kaila

Avait le même problème aujourd'hui . Après quelques recherches j'ai trouvé une option très utile --abort-on-uncaught-exception node.js . Non seulement il fournit une trace de pile d'erreur beaucoup plus détaillée et utile, mais il enregistre également le fichier principal en cas de blocage de l'application, permettant ainsi un débogage ultérieur.

12
stainful

Oui, votre distribution du fichier de stratégie peut provoquer le blocage.

Pour répéter, ajoutez simplement un délai à votre code:

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

… Et utilisez telnet pour vous connecter au port. Si vous déconnectez telnet avant l'expiration du délai, vous obtenez un blocage (exception non capturée) lorsque socket.write renvoie une erreur.

Pour éviter le crash ici, ajoutez simplement un gestionnaire d’erreur avant de lire/écrire le socket:

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

Lorsque vous essayez de vous déconnecter, vous obtenez simplement un message de journal au lieu d’un blocage.

Et lorsque vous avez terminé, n'oubliez pas de supprimer le délai.

7
Joachim Isaksson

Un autre cas possible (mais rare) pourrait être si vous avez des communications de serveur à serveur et que vous avez défini server.maxConnections sur une valeur très faible.

Dans le noyau central du noeud, lib net.js il appellera clientHandle.close(), ce qui provoquera également l'erreur ECONNRESET:

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

Je reçois également une erreur ECONNRESET au cours de mon développement. La façon dont je le résous est d'utiliser not en utilisant nodemon pour démarrer mon serveur. Il suffit d'utiliser "node server.js" pour démarrer mon serveur, ce qui corrige mon problème. 

C'est bizarre, mais cela a fonctionné pour moi. Maintenant, je ne revois plus jamais l'erreur ECONNRESET.

2
Andrew Lam

J'ai résolu le problème simplement en se connectant à un autre réseau . C'est l'un des problèmes possibles.

Comme indiqué ci-dessus, ECONNRESET signifie que la conversation TCP a fermé brutalement sa fin de la connexion. 

Votre connexion Internet peut vous empêcher de vous connecter à certains serveurs. Dans mon cas, j'essayais de me connecter à mLab (service de base de données cloud hébergeant des bases de données MongoDB). Et mon FAI le bloque. 

1
Yousef

J'ai eu aussi cette erreur et j'ai pu la résoudre après des jours de débogage et d'analyse:

ma solution

Pour moi, VirtualBox (pour Docker) était le problème. Le transfert de port était configuré sur mon VM et l'erreur ne se produisait que sur le port transféré.

conclusions générales

Les observations suivantes peuvent vous faire économiser des jours de travail que j'ai dû investir:

  • Pour moi, le problème ne s'est produit que sur les connexions de localhost à localhost sur un port. -> cocher la modification de l’une ou l’autre de ces constantes résout le problème.
  • Pour moi, le problème ne s'est produit que sur ma machine -> laissez quelqu'un d'autre l'essayer.
  • Pour moi, le problème ne s'est produit qu'après un moment et n'a pas pu être reproduit de manière fiable.
  • Mon problème n'a pu être inspecté avec aucun des nœuds ou des outils de débogage. -> ne perds pas de temps à ça

-> déterminer si quelque chose perturbe votre réseau (paramètres), tels que les VM, les pare-feu, etc.

1
Waog

J'ai résolu ce problème en:

  • Désactiver ma connexion wifi/ethernet et l'allumer. 
  • J'ai tapé: npm update dans le terminal pour mettre à jour npm.
  • J'ai essayé de me déconnecter de la session et de me reconnecter

Après cela, j'ai essayé la même commande npm et la bonne chose était que cela fonctionnait. Je n'étais pas sûr que ce soit aussi simple.

J'utilise CENTOS 7

0
muhammad tayyab

Essayez d’ajouter ces options à socket.io:

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

J'espère que cela t'aidera !

0
sol404