WedX - журнал о программировании и компьютерных науках

Как отладить ошибку ECONNRESET в Node.js?

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

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

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

Это ошибка узла 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

ИЗМЕНИТЬ (22 июля 2013 г.)

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

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

Поэтому я подозреваю, что это не проблема Socket.io, а HTTP-запрос к другому серверу, который я делаю, или соединение MySQL / Redis. Проблема в том, что стек ошибок не помогает мне определить проблему с кодом. Вот результат журнала:

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

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

Хорошо, не очень многословно, но вот трассировка стека с Лонгджоном:

    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] ] } }

Здесь я обслуживаю файл политики флеш-сокета:

    net = require("net")
    net.createServer( (socket) =>
      socket.write("<?xml version=\"1.0\"?>\n")
      socket.write("<!DOCTYPE cross-domain-policy SYSTEM \"https://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)

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

21.06.2013

  • @GottZ, возможно, это может помочь (поговорил с кем-то, кто работает с node js) gist.github.com/samsonradu/1b0c6feb430e5a53e. Сегодня я разверну обработчик socket.error и дам вам знать. 25.06.2013
  • @Gottz, который обрабатывает socket.error, не помогает, но process.on ('uncaughtException') перехватывает ошибку. Вот журнал console.log ошибки: {[Ошибка: чтение ECONNRESET] код: 'ECONNRESET', номер ошибки: 'ECONNRESET', системный вызов: 'чтение'} 04.07.2013
  • ECONNRESET может быть из-за проблемы с сетью. Как известно, при тестировании невозможно отловить все исключения. Некоторые из них появятся на вашем рабочем сервере. Вам нужно будет сделать свой сервер надежным. Вы можете обработать удаление сеанса, используя Redis в качестве хранилища. Это заставляет ваши сеансы сохраняться даже после того, как ваш сервер узла выходит из строя. 08.07.2013
  • Почему это связано с удалением сеанса? В любом случае они обрабатываются Redis. 08.07.2013
  • Мне кажется, что вы получаете тайм-аут сокета от одного из ваших подключенных клиентов. Попробуйте добавить прослушиватель ошибок ко всем вашим соединениям, а не к самому процессу. 08.07.2013
  • net.js выполняет много отладочных операций, когда собирается выдать ошибку, вы можете немного сэкономить, установив env.NODE_DEBUG = net, а затем сопоставив вывод с исходными местоположениями. 09.07.2013
  • @Moss определяет подключенных клиентов. Сервер узла прослушивает только соединения с веб-сокетами, и к ним добавлен обработчик ошибок. 10.07.2013
  • У вас есть хотя бы один прослушивающий TCP-сокет, для которого не установлен обработчик. Итак, теперь пора проверить, где он: D 10.07.2013
  • просто как примечание: в моем случае это происходит с дочерним процессом stdio, а не с tcp-сокетом или чем-то еще. просто сырой stdio. сейчас попробует это событие uncaughtException. Благодарю. 11.07.2013
  • Можете ли вы показать соответствующий код с вашего сервера, на котором возникает ошибка. Или хотя бы минимальный код для воспроизведения ошибки. Без взгляда на код это сложно. 16.07.2013
  • @ user568109, вот несколько важных частей (если вас устраивает Coffeescript) gist.github.com/samsonradu/5585b0f3cab4a101 16.07.2013
  • github.com/joyent/node/releases/tag/v0.10.12 увидев исправление записи сокета. будет обновляться 16.07.2013
  • Простое добавление process.on('uncaughtException', function (err) { ... }) помогло мне решить эту проблему. Это не доходит до корня проблемы, но ошибка достаточно редка для меня, и это быстрое и грязное решение подходит для моего варианта использования. 06.04.2017
  • Связано: если кто-то видит, что это происходит в некоторых предложениях облака / PaaS, это может быть связано с тем, что экземпляры замедляются (в спокойное время). 27.06.2018

Ответы:


1

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

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

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

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

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

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

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

ИЗМЕНИТЬ (22 июля 2013 г.)

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

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

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

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

14.07.2013
  • Это не обязательно должно означать «внезапно закрыто». Обычно это происходит в результате записи в соединение, которое одноранговый узел уже нормально закрыл. Это приведет к выдаче RST. 07.04.2014
  • @EJP Я написал «отрывисто» не зря. Ошибка (не предупреждение) указывает, что соединение было сброшено одноранговым узлом. Существующее соединение было принудительно закрыто удаленным узлом. Принудительное закрытие произошло внезапно из-за неожиданности! (Обычно это происходит, если одноранговое приложение на удаленном компьютере внезапно останавливается, компьютер перезагружается или одноранговое приложение использовало жесткое закрытие удаленного сокета. Эта ошибка также может возникнуть, если соединение было прервано из-за активности поддержания активности, обнаружившей сбой во время одна или несколько операций выполняются ... эти операции и последующие операции завершатся ошибкой.) 07.04.2014
  • Я получаю эту ошибку, когда одновременно отправляю около 100 вызовов API из браузера (Chrome) для тестирования. Я предполагаю, что тогда Chrome должен стать перегруженным и убить некоторые соединения ... @Samson - что плохого в обработке каждого запроса в собственном домене и обнаружении ошибок домена без перезапуска сервера? 10.07.2014
  • @supershnee Вы должны почти всегда перезапускать сервер после неперехваченного исключения, поскольку ваши данные, приложение и сам node.js находятся в неизвестном состоянии. Продолжение после исключения подвергает ваши данные риску. Если вы хотите узнать больше, ознакомьтесь с документацией узла по процессу или документацию узла по доменам. 31.08.2015

  • 2

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

    # 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 \"https://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)
    
    23.07.2013
  • Что-то не так с кодом? Должен ли я перед записью проверять, доступен ли сокет для записи? 23.07.2013
  • Дох, не видел, что вы уже нашли решение, прежде чем я опубликовал почти то же самое :) Что касается вашего вопроса, хотя, даже если вы проверите, что сокет доступен для записи, это может быть не так, когда вы напишете в него микросекунды позже и все равно выдаст ошибку, так что это способ убедиться. 23.07.2013
  • хорошо, и есть ли безопасный выход из этого? как socket.close () внутри обработчика ошибок? потому что я думаю, что загрузка моего процессора увеличивается после этих ошибок (не уверен) 23.07.2013
  • Я всегда вызывал socket.destroy() в обработчике ошибок, чтобы убедиться. К сожалению, я не могу найти документацию, требуется ли она, но при этом ошибки не возникает. 23.07.2013
  • socket.destroy () спас мне день, независимо от того, что работает !! Спасибо! 29.10.2016

  • 3

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

    • net: не подавлять ECONNRESET (Бен Нордхейс)

    В предыдущих версиях не возникало ошибок при прерывании работы клиента. Разрыв соединения от клиента вызывает ошибку ECONNRESET в Node. Я считаю, что это предназначенная функция для Node, поэтому исправление (по крайней мере, для меня) заключалось в обработке ошибки, что, как я полагаю, вы сделали в исключениях unCaught. Хотя я обрабатываю это в обработчике net.socket.

    Вы можете продемонстрировать это:

    Сделайте простой сервер сокетов и получите 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)

    Вы должны увидеть NO ERROR при использовании Node v0.9.9 и ERROR при использовании Node v.0.9.10 и выше.

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

    22.07.2013
  • Спасибо, сам прибил! Важно не допустить распространения ошибок в uncaughtException, поскольку это делает все приложение нестабильным. Например. после обнаружения около 10 ошибок ECONNRESET сервер иногда переставал отвечать (просто зависал и не обрабатывал соединения) 23.07.2013
  • Также знал об изменении версии узла, которое больше не подавляло ошибку, но, видя так много проблем, обнаруживаемых и решаемых в каждой версии, я предпочел бы выбрать последнюю. Сейчас я использую V0.10.13, кстати 23.07.2013

  • 4

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

    29.06.2015
  • странно, что новый ответ на этот старый вопрос должен появиться, когда я смотрю - но это здорово, спасибо 29.06.2015

  • 5

    Я столкнулся с той же проблемой, но я решил ее решить, разместив:

    server.timeout = 0;
    

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

    28.10.2014
  • Это не решение, а скорее быстрое исправление, которое ломает вещи, не вызывая ошибки. 12.02.2018
  • Я считаю, что для меня проблема заключалась в том, что время ожидания истекло через 5 минут или около того, это все равно будет проблемой? 23.07.2020
  • Отсутствие тайм-аута может сделать вас уязвимым для DOS через http-векторы 10.09.2020

  • 6

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

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

    26.04.2018
  • Есть идеи, как вы пришли к этому решению? Вы просто случайно попробовали. Мне это тоже помогло. 06.09.2020

  • 7

    Другой возможный случай (но редкий) может быть, если у вас есть связь между серверами и для server.maxConnections установлено очень низкое значение.

    В основной библиотеке узла net.js будет вызовите clientHandle.close(), который также вызовет ошибку ECONNRESET:

    if (self.maxConnections && self._connections >= self.maxConnections) {
      clientHandle.close(); // causes ECONNRESET on the other end
      return;
    }
    
    07.10.2016
  • Отличный вызов, но maxConnections значение по умолчанию - Infinity. Это будет только в том случае (как вы сказали), если вы явно переопределили это значение. 15.07.2019

  • 8

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

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

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

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

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

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

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

    И когда вы закончите, не забудьте убрать задержку.

    23.07.2013

    9

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

    мое решение

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

    общие выводы

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

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

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

    04.05.2018

    10

    Я решил эту проблему:

    • Выключаю Wi-Fi / Ethernet-соединение и включаю.
    • Я набрал: npm update в терминале, чтобы обновить npm.
    • Я попытался выйти из сеанса и снова войти в систему

    После этого я попробовал ту же команду npm, и хорошо, что это сработало. Я не был уверен, что это так просто.

    Я использую CENTOS 7

    25.02.2019

    11

    Я только что понял это, по крайней мере, в моем случае использования.

    Я получал ECONNRESET. Оказалось, что мой клиент был настроен так, что он много раз обращался к серверу с вызовом API очень быстро - и ему нужно было только один раз попасть в конечную точку.

    Когда я исправил это, ошибка исчезла.

    24.05.2020

    12

    Я решил проблему, просто подключившись к другой сети. Это одна из возможных проблем.

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

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

    10.02.2018
  • Этот сработал для меня, мой код, который работал нормально несколько часов назад, внезапно перестал работать, оказывается, изменение сети вызвало проблему 12.04.2018

  • 13

    ECONNRESET происходит, когда сторона сервера закрывает TCP-соединение и ваш запрос к серверу не выполняется. Сервер отвечает сообщением о том, что соединение, вы имеете в виду недопустимое соединение.

    Почему сервер отправляет запрос с недопустимым соединением?

    Предположим, вы включили постоянное соединение между клиентом и сервером. Таймаут проверки активности настроен на 15 секунд. Это означает, что если keep-alive бездействует в течение 15 секунд, он отправит запрос на закрытие соединения. Таким образом, через 15 секунд сервер говорит клиенту закрыть соединение. НО, когда сервер отправляет этот запрос, клиент отправляет новый запрос, который уже находится в полете на стороне сервера. Поскольку сейчас это соединение недействительно, сервер отклонит сообщение с ошибкой ECONNRESET. Таким образом, проблема возникает из-за меньшего количества запросов к серверу. Поэтому, пожалуйста, отключите keep-alive, и он будет работать нормально.

    06.06.2021

    14

    У меня была такая же проблема, и похоже, что проблема была в версии Node.js.

    Я установил предыдущую версию Node.js (10.14.2), и все было в порядке с использованием nvm (позволяет установить несколько версий Node.js и быстро переключаться с одной версии на другую).

    Это не «чистое» решение, но оно может служить вам временно.

    19.12.2019

    15

    Сокет Node JS не блокирует io. Рассмотрите возможность использования неблокирующего io-соединения из других источников. Например, если вы используете блокирующий сокет Java с узлом, он будет работать только в течение нескольких секунд, после чего будет выдана ошибка. Смягчите это, реализовав неблокирующее соединение, т. Е. socketchannel с селектором.

    05.06.2021

    16

    Попробуйте добавить эти параметры в socket.io:

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

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

    19.04.2018
    Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]