Nó js ECONNRESET

Eu estou executando uma aplicação Express js com socket.io para uma aplicação web chat e recebo o seguinte erro aleatoriamente em torno de 5 vezes durante 24h. O processo do nó é empacotado para sempre e se reinicia imediatamente.

O problema é que a reboot expressa expulsa meus usuários de seus quartos e ninguém quer isso.

O servidor web é proxied por HAProxy. Não há problemas de estabilidade de soquete, usando apenas websockets e transportes de flashsockets. Eu não posso reproduzir isso de propósito.

Este é o erro com o nó v0.10.11:

events.js:72 throw er; // Unhandled 'error' event ^ Error: read ECONNRESET //alternatively it sa '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)

Adicionado o manipulador de erros do cliente socket.io e o manipulador de exceções não-identificado. Parece que este pega o erro:

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

Então eu suspeito que não é um problema de socket.io, mas um pedido de http para outro servidor que eu faço ou uma conexão mysql / redis. O problema é que a pilha de erros não ajuda a identificar meu problema de código. Aqui está a saída do log:

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

Como eu sei o que causa isso? Como obtenho mais do erro?

Ok, não muito verboso, mas aqui está o stacktrace com “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] ] } } 

Aqui eu sirvo o arquivo de política de soquete flash:

 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) 

Isso pode ser a causa?

Você já deve ter adivinhado: é um erro de conexão.

“ECONNRESET” significa que o outro lado da conversa TCP encerrou abruptamente o final da conexão. Isso é provavelmente devido a um ou mais erros do protocolo de aplicativo. Você pode ver os logs do servidor de API para ver se ele reclama de algo.

Mas como você também está procurando uma maneira de verificar o erro e potencialmente depurar o problema, você deve dar uma olhada em ” Como depurar um erro de interrupção do soquete no NodeJS? “, Que foi postado em stackoverflow em relação a uma pergunta semelhante.

Solução rápida e suja para desenvolvimento :

Use longjohn , você obtém rastreios de pilha longos que conterão as operações assíncronas.

Solução limpa e correta : Tecnicamente, no nó, sempre que você emitir um evento de 'error' e ninguém o escutar, ele emitirá . Para não jogar, coloque um ouvinte nele e cuide de você. Dessa forma, você pode registrar o erro com mais informações.

Para ter um ouvinte para um grupo de chamadas, você pode usar domínios e também capturar outros erros no tempo de execução. Certifique-se de que cada operação assíncrona relacionada a http (Servidor / Cliente) esteja em contexto de domínio diferente, comparando com as outras partes do código, o domínio escutará automaticamente os events de error e os propagará para seu próprio manipulador. Então você só escuta esse manipulador e obtém os dados de erro. Você também recebe mais informações gratuitamente.

EDIT (2013-07-22)

Como escrevi acima:

“ECONNRESET” significa que o outro lado da conversa TCP encerrou abruptamente o final da conexão. Isso é provavelmente devido a um ou mais erros do protocolo de aplicativo. Você pode ver os logs do servidor de API para ver se ele reclama de algo.

O que também poderia ser o caso: em momentos randoms, o outro lado está sobrecarregado e simplesmente mata a conexão como resultado. Se for esse o caso, depende do que você está se conectando exatamente …

Mas uma coisa é certa: você realmente tem um erro de leitura em sua conexão TCP que causa a exceção. Você pode ver isso observando o código de erro que você postou na sua edição, o que confirma isso.

Um servidor tcp simples que eu tinha para servir o arquivo de política flash estava causando isso. Agora eu posso pegar o erro usando um manipulador:

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

Eu tive um problema semelhante, onde os aplicativos começaram a errar após uma atualização do Node. Eu acredito que isso pode ser rastreado até o lançamento do Nó v0.9.10 neste item:

  • net: não suprima ECONNRESET (Ben Noordhuis)

Versões anteriores não causariam erros nas interrupções do cliente. Uma quebra na conexão do cliente gera o erro ECONNRESET no nó. Acredito que essa seja a funcionalidade pretendida para o Node, portanto, a correção (pelo menos para mim) era lidar com o erro, o que acredito que você fez em exceções do unCaught. Apesar de lidar com isso no manipulador net.socket.

Você pode demonstrar isso:

Crie um servidor de soquete simples e obtenha o Nó v0.9.9 e v0.9.10.

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

Inicie-o usando v0.9.9 e tente FTP para este servidor. Estou usando o FTP e a porta 21 apenas porque estou no Windows e tenho um cliente FTP, mas nenhum cliente telnet acessível.

Então, do lado do cliente, apenas interrompa a conexão. (Eu só estou fazendo Ctrl-C)

Você deverá ver NO ERROR ao usar o Nó v0.9.9 e ERROR ao usar o Nó v.0.9.10 e superior.

Na produção, eu uso v.0.10. algo e ainda dá o erro. Novamente, acho que isso é intencional e a solução é lidar com o erro em seu código.

Tive o mesmo problema hoje. Depois de algumas pesquisas eu encontrei uma opção muito útil --abort-on-uncaught-exception node.js. Isso não apenas fornece um rastreamento de pilha de erros muito mais detalhado e detalhado, mas também salva o arquivo principal na falha do aplicativo, permitindo uma debugging adicional.

Eu estava enfrentando o mesmo problema, mas eu o abriguei colocando:

 server.timeout = 0; 

antes de server.listen . server é um servidor HTTP aqui. O tempo limite padrão é de 2 minutos, conforme a documentação da API .

Sim, sua veiculação do arquivo de políticas pode causar a falha.

Para repetir, basta adicionar um atraso ao seu código:

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

… E use o telnet para se conectar à porta. Se você desconectar o telnet antes que o atraso tenha expirado, você obterá uma falha (exceção não identificada) quando o socket.write exibir um erro.

Para evitar a falha aqui, basta adicionar um manipulador de erro antes de ler / gravar o soquete:

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

Quando você tentar a desconexão acima, você só receberá uma mensagem de log em vez de uma falha.

E quando terminar, lembre-se de remover o atraso.

Outro caso possível (mas raro) pode ser se você tiver comunicações de servidor para servidor e tiver definido server.maxConnections como um valor muito baixo.

No core do node lib net.js ele chamará o clientHandle.close() que também causará o erro ECONNRESET:

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

Eu resolvi o problema simplesmente conectando a uma rede diferente . Esse é um dos possíveis problemas.

Como discutido acima, o ECONNRESET significa que a conversa TCP encerrou abruptamente o fim da conexão.

Sua conexão com a Internet pode estar bloqueando você de se conectar a alguns servidores. No meu caso, eu estava tentando me conectar ao mLab (serviço de database em nuvem que hospeda bancos de dados do MongoDB). E meu provedor está bloqueando isso.

Eu também recebo erro ECONNRESET durante o meu desenvolvimento, a maneira que eu resolvo é por não usar o nodemon para iniciar o meu servidor, basta usar o "node server.js" para iniciar o meu servidor corrigido o meu problema.

É estranho, mas funcionou para mim, agora eu nunca mais vejo o erro ECONNRESET.

Eu tive esse erro também e foi capaz de resolvê-lo depois de dias de debugging e análise:

minha solução

Para mim, VirtualBox (para Docker) foi o problema. Eu tinha Port Forwarding configurado na minha VM e o erro só ocorreu na porta encaminhada.

conclusões gerais

As seguintes observações podem poupar-lhe dias de trabalho que tive de investir:

  • Para mim, o problema ocorreu apenas nas conexões de localhost para localhost em uma porta. -> verifique se alterar qualquer uma dessas constantes resolve o problema.
  • Para mim, o problema só ocorreu na minha máquina -> deixar alguém tentar.
  • Para mim, o problema só ocorreu depois de um tempo e não podia ser reproduzido de forma confiável
  • Meu problema não pode ser inspecionado com nenhum dos nós ou expressa (debugging) ferramentas. -> não perca tempo com isso

-> descobrir se algo está mexendo com sua rede (configurações), como VMs, firewalls etc, esta é provavelmente a causa do problema.

Tente adicionar essas opções ao socket.io:

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

Eu espero que isso te ajude !