Узел 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 };
Я надеюсь, что это поможет вам !