Узел JS ECONNRESET

я запускаю приложение Express js с сокетом.io для чата webapp и я получаем следующую ошибку случайным образом около 5 раз во время 24 часа. Процесс узла завернут в forever и перезапускается сама немедленно.

проблема в том, что перезапуск express выбивает моих пользователей из их комнат и никто этого не хочет.

веб-сервер проксируется HAProxy. Нет проблем со стабильностью сокетов, просто используя websockets и flashsockets-транспорты. Я не могу воспроизвести это нарочно.

это ошибка с узлом 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)

добавлены оба сокета.обработчик ошибок клиента ввода-вывода и обработчик необнаруженных исключений. Кажется, что этот ловит ошибку:

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

поэтому я подозреваю, что это не розетка.проблема ввода-вывода, но http-запрос на другой сервер, который я делаю, или соединение mysql/redis. Проблема в том, что стек ошибок не помогает мне идентифицировать проблему с кодом. Вот вывод журнала:

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

как узнать, что вызывает это? Как я могу получить больше от ошибки?

хорошо, не очень многословно, но вот stacktrace с "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] ] } }

здесь я обслуживаю файл политики flash socket:

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)

может ли это быть причиной?

11 ответов


Вы, наверное, уже догадались: это ошибка подключения.

"ECONNRESET" означает, что другая сторона разговора TCP резко закрыла свой конец соединения. Это, скорее всего, связано с одной или несколькими ошибками протокола приложения. Вы можете посмотреть журналы сервера API, чтобы узнать, жалуется ли он на что-то.

но поскольку вы также ищете способ проверить ошибку и потенциально отладить проблему, вы должны взглянуть на "как отладить ошибку зависания сокета в NodeJS?" который был размещен в stackoverflow по отношению к аналогичному вопросу.

быстрое и грязное решение для развития:

использовать longjohn, вы получаете длинные трассировки стека, которые будут содержать асинхронные операции.

чистота и правильное решение: Технически, в узле, когда вы испускают 'error' событие и никто его не слушает, он бросит. Чтобы его не кинуть, поставьте на него слушателя и разберитесь с ним сами. Таким образом, вы можете зарегистрировать ошибку с дополнительной информацией.

чтобы иметь один прослушиватель для группы вызовов, вы можете использовать Домены, а также поймать другие ошибки во время выполнения. Убедитесь, что каждая асинхронная операция, связанная с http (сервер / клиент), находится в другом домен контексте по сравнению с другими частями кода, домен будет автоматически слушайте error события и будет распространять его на собственный обработчик. Таким образом, вы слушаете только этот обработчик и получаете данные об ошибках. вы также получаете больше информации бесплатно.

EDIT (2013-07-22)

Как я писал выше:

"ECONNRESET" означает, что другая сторона разговора TCP резко закрыла свой конец соединения. Это, скорее всего, связано с одним или несколькими протоколами приложений ошибки. Вы можете посмотреть журналы сервера API, чтобы узнать, жалуется ли он на что-то.

что также может быть: в случайные моменты другая сторона перегружена и просто убивает соединение в результате. Если это так, зависит от того, к чему вы подключаетесь точно...

но одно можно сказать наверняка: у вас действительно есть ошибка чтения в вашем TCP-соединении, которая вызывает исключение. Вы можете увидеть это, посмотрев на код ошибки, который вы опубликовали в своем редактировании, который подтвердить это.


простой tcp-сервер, который у меня был для обслуживания файла политики flash, вызывал это. Теперь я могу поймать ошибку с помощью обработчика:

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

У меня была аналогичная проблема, когда приложения начали ошибаться после обновления узла. Я считаю, что это можно проследить до выпуска узла v0.9.10 Этот пункт:

  • net: не подавляйте ECONNRESET (Ben Noordhuis)

предыдущие версии не будут ошибаться при прерываниях от клиента. Разрыв соединения от клиента вызывает ошибку ECONNRESET в узле. Я считаю, что это предназначено для 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)

вы не увидите ошибки при использовании узла v0.9.9, и ошибка при использовании узла V. 0.9.10 и выше.

в производстве я использую V. 0.10. что-то и это все равно дает ошибку. Опять же, я думаю, что это предназначено, и решение заключается в обработке ошибки в вашем коде.


я столкнулся с той же проблемой, но я смягчил ее, поместив:

server.timeout = 0;

до server.listen. server является HTTP-сервером здесь. Время ожидания по умолчанию составляет 2 минуты на документация API.


сегодня была та же проблема. После некоторых исследований я нашел очень полезным --abort-on-uncaught-exception узел.вариант с JS. Он не только обеспечивает гораздо более подробную и полезную трассировку стека ошибок, но и сохраняет основной файл при сбое приложения, позволяя дальнейшую отладку.


Да, ваша подача файла политики может определенно вызвать сбой.

чтобы повторить, просто добавьте задержку в свой код:

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

и telnet для подключения к порту. Если вы отключите telnet до истечения срока задержки, вы получите сбой (необработанное исключение), когда сокет.записи выдает ошибку.

чтобы избежать сбоя здесь, просто добавьте обработчик ошибок перед чтением / записью сокета:

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 означает, что разговор TCP резко закрыл свой конец соединения.

подключение к сети может блокировать подключение к некоторым серверам. В моем случае я пытался подключиться к mLab (службе облачных баз данных, в которой размещаются базы данных MongoDB). И мой провайдер блокирует его.


Я также получаю ошибку ECONNRESET во время моей разработки, так как я решаю ее с помощью не используя nodemon для запуска моего сервера, просто используйте "node server.js" для запуска моего сервера исправлена моя проблема.

это странно, но это сработало для меня, теперь я никогда не вижу ошибку ECONNRESET снова.


У меня тоже была эта ошибка и я смог ее решить после нескольких дней отладки и анализа:

мое решение

для меня VirtualBox (для Docker) была проблемой. У меня была переадресация портов, настроенная на моей виртуальной машине, и ошибка произошла только на перенаправленном порту.

общие выводы

следующие наблюдения могут сэкономить Вам дни работы, которые я должен был инвестировать:

  • для меня проблема возникла только при соединениях с localhost на localhost на одном порту. - >проверка изменения любой из этих констант решает проблему.
  • для меня проблема только на моей машине -пусть кто-нибудь попробует его.
  • для меня проблема возникла только через некоторое время и не могла быть воспроизведена достоверно
  • моя проблема не может быть проверена с помощью любого из узлов или инструментов expresses (debug -). - > не тратьте время на это

-> выясните, если что-то возится с вашим сеть (настройки), как ВМ, брандмауэры и т. д. это, вероятно, и есть причина проблемы.


попробуйте добавить эти параметры в сокет.Ио:

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

Я надеюсь, что это поможет вам !