Вузол js ECONNRESET

Я запускаю програму Express JS з socket.io для чату    webapp, і я отримую наступну помилку випадково близько 5 раз протягом    Цілодобово Процес вузла завершується назавжди, і він перезапускається    сама відразу

Проблема полягає в тому, що перезапуск виражає моїх користувачів з їхніх кімнат    і ніхто цього не хоче.

Веб-сервер проксі-сервером 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

EDIT (2013-07-22)

Додано як обробник обробки помилок клієнта 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)

Як я знаю, що викликає це? Як я можу отримати більше від помилки?

Гаразд, не дуже багатослівно, але ось стаккрейка з "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:

net = require("net")
net.createServer( (socket) =>
  socket.write("<?xml version=\"1.0\"?>\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.end()
).listen(843)

Чи може це бути причиною?

196
Просто додавання process.on ('uncaughtException', функція (err) {...}) сортувала це для мене. Це не потрапляє в корінь проблеми, але для мене досить рідко, що це швидке та брудне рішення чудово для мого випадку використання.
додано Автор JoeRocc, джерело
ECONNRESET може бути з мережевої проблеми. Як ви знаєте, неможливо зловити всі винятки при тестуванні. Деякі з них з'являться на вашому виробничому сервері. Вам доведеться зробити ваш сервер надійним. Ви можете обробляти видалення сеансу, використовуючи Redis як сховище. Це робить ваші сесії зберігаються навіть після того, як ваш сервер вузла знижується.
додано Автор user568109, джерело
Ви можете показати відповідний код з вашого сервера, де виникає помилка. Або хоча б якийсь мінімальний код для відтворення помилки. Це важко, не дивлячись на код.
додано Автор user568109, джерело
Відповідний: якщо хтось бачить це, що відбувається за деякими пропозиціями хмара/PaaS, це може бути тому, що екземпляри зводяться вниз (у тихий час).
додано Автор opyate, джерело
як і примітка: у моєму випадку це відбувається з childprocesses stdio, а не через tcp роз'єм або що-небудь ще. тільки сирий stdio. буде спробувати цю незрозумілу подія виключення зараз. Дякую.
додано Автор GottZ, джерело
@Gottz ручки socket.error не допомагають, але process.on ('uncaughtException') сповіщає про помилку. Ось консоль.log помилки: {[Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read')
додано Автор Samson, джерело
github.com/joyent/node/releases/tag/v0.10.12 бачить виправлення для сокета пише. буде оновлено
додано Автор Samson, джерело
@ user568109 Тут наведені деякі релевантні частини (якщо ви згодні з Coffeescript) gist.github.com/samsonradu/5585b0f4a101fee3cab4
додано Автор Samson, джерело
@Moss визначити зв'язані клієнти. Сервер вузла прослуховує лише з'єднання веб-вузлів, і до них додано обробник помилок.
додано Автор Samson, джерело
Чому це пов'язано з видаленням сеансу? Усе це поводяться Редісом.
додано Автор Samson, джерело
@GottZ, може, це може допомогти (розмовляли з тими, хто працює в вузлах js) gist.github.com/samsonradu/1b0c6feb438f5a53e30e Я буду розгортати обробник socket.error сьогодні і повідомити вас.
додано Автор Samson, джерело
Ви маєте принаймні одне прослуховування сокету TCP, яке не має встановленого обробника. Отже, настав час перевірити, де це таке: D
додано Автор Moss, джерело
Це збігається зі мною, оскільки ви отримуєте тайм-аут розеток з одного з ваших пов'язаних клієнтів. Спробуйте додати "помилку" слухачеві на всі ваші зв'язки, а не сам процес.
додано Автор Moss, джерело
net.js багато дебаг-логів, коли він буде випускати помилку, ви можете отримати певний пробіг у налаштуваннях env.NODE_DEBUG = "net", а потім узгодити вихідний сигнал з розташуванням джерела.
додано Автор jjm, джерело

11 Відповіді

Ви вже могли це здогадуватися: це помилка з'єднання.

"ECONNRESET" means the other side of the TCP conversation abruptly closed its end of the connection. This is most probably due to one or more application protocol errors. You could look at the API server logs to see if it complains about something.

Але оскільки ви також шукаєте спосіб перевірити помилку та, можливо, усуваєте проблему, слід поглянути на " Як для налагодження сокета виникла помилка в NodeJS? , яка була опублікована в stackoverflow по відношенню до подібного питання.

Швидкий та брудний рішення для розробки :

     

Використовуйте longjohn , ви отримуєте довгі сліди зі стеком, які містять операції асинхронізації.

     

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

     

Щоб мати одного слухача для групи дзвінків, ви можете використовувати домени , а також витягнути інші помилки при виконанні. Переконайтеся, що кожна операція асинхронного зв'язку, пов'язана з http (Server/Client), знаходиться в різному контексті порівняння домену до інших частин коду, домен буде автоматично прослуховувати події error і поширюватиме його на власний обробник. Таким чином, ви тільки слухаєте цього обробника та отримуєте дані про помилку. Ви також отримуєте додаткову інформацію безкоштовно.

EDIT (2013-07-22)

Як я писав вище:

"ECONNRESET" означає, що інша сторона розмови TCP різко закрила його кінець з'єднання. Ймовірно, це пов'язано з однією або кількома помилками протоколу додатків. Ви можете переглянути журнали сервера API, щоб дізнатись, чи це щось скаржиться.

Що може статися так само: у випадкових випадках інша сторона перевантажена і просто вбиває зв'язок в результаті. Якщо це так, залежить від того, до чого ви точно підключаєтеся ...

Але одна справа напевно: у вас дійсно є помилка читання у вашому TCP-з'єднанні, що викликає виняток. Ви можете побачити це, подивившись код помилки, який ви опублікували у вашому редакторі, що підтверджує це.

183
додано
Це не повинно означати "круто закриті". Як правило, це виникає при написанні до з'єднання, яке peer вже закрило нормально. Це призведе до випуску RST.
додано Автор EJP, джерело
@supershnee Вам слід майже завжди перезавантажувати сервер після невичерпного винятку, оскільки ваші дані, додаток та вузол node.js самі по собі невідомі. Продовження після виключення ставить ваші дані ризиком. Якщо ви хочете дізнатись більше, перегляньте документи вузла в процесі . або документи вузла на доменах .
додано Автор c1moore, джерело
@EJP Існує вагома причина, чому я написав "круто". Помилка (не попередження) вказує на те, що з'єднання було скинуто за допомогою peer. Існуюче з'єднання було примусово закрито віддаленим рівнем доступу. Примусовий закриття круто, оскільки несподівано! (Це, як правило, відбувається, якщо однорангове додаток на віддаленій машині раптово зупиняється, машина перезавантажується, або однорангове додаток використовується на "жорсткому закритті" на пульті розетки. Ця помилка також може бути результатом, якщо з'єднання було зламано через активність "keep-alive" виявлення несправності, коли виконується одна або більше операцій ... ці операції та наступні операції вийдуть з ладу).
додано Автор e-sushi, джерело
Я отримую цю помилку, коли я відправляю близько 100 викликів API одночасно з браузера (Chrome) для тестування. Я думаю, що Chrome повинен перевантажуватись і вбити деякі з'єднання ... @Samson - що трапилось при обробці кожного запиту в його власному домені та лову помилок домену без перезавантаження сервера?
додано Автор supershnee, джерело

Це викликало простий сервер tcp, який я мав для обслуговування файлу flash policy. Тепер я можу зловити помилку, використовуючи обробник:

# 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("\n")
  socket.write("\n")
  socket.write("\n")
  socket.write("\n")
  socket.end()
).listen(843)
28
додано
Я завжди називаю socket.destroy() в обробнику помилок, щоб переконатися. На жаль, я не можу знайти документацію, чи потрібна вона, але це не видає помилку.
додано Автор Joachim Isaksson, джерело
Doh, не бачив, що ви вже знайшли рішення, перш ніж я опублікував приблизно те ж саме: Що стосується вашого питання, навіть якщо ви перевіряєте, чи сокета доступний для запису, він може бути не тоді, коли ви пишете на нього мікросекунди пізніше і все одно буде викидати помилку, так що це "спосіб" бути впевненим.
додано Автор Joachim Isaksson, джерело
добре, і чи є безпечний вихід, якщо це? як socket.close() всередині обробника помилок? тому що я думаю, що мій процесор завантажується після цих помилок (не впевнений)
додано Автор Samson, джерело
Чи є щось погане з кодом? Чи повинен я перевірити, чи сокет можна записати до написання?
додано Автор Samson, джерело
socket.destroy() врятував мій день, що б не було! Дякую!
додано Автор Firas Abd Alrahman, джерело

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

  • net: не пригнічуйте ECONNRESET (Ben Noordhuis)

Попередні версії не призведуть до помилок при перериванні від клієнта. Перерва у зв'язку з клієнтом видає помилку ECONNRESET в вузлі. Я вважаю, що це призначена для вузла функціональність, тому виправлення (принаймні для мене) полягало в тому, щоб впоратись з помилкою, яку, як ви вважаєте, зробили з винятками. Хоча я обробляю це в обробнику net.socket.

Ви можете продемонструвати це:

Зробіть простий сокет-сервер і отримайте вузол 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. щось і все одно дає помилку. Знову ж таки, я думаю, що це призначено, і рішенням є обробка помилки у вашому коді.

21
додано
Також знав про зміну версії вузла, яка більше не придушувала помилку, але, бачачи так багато проблем, що з'являються і вирішуються кожна версія, я швидше йду за останньою. Я використав V0.10.13 тепер бір
додано Автор Samson, джерело
Спасибі, я прибила це себе! Важливо не допускати поширення помилок на неприховану виключення, оскільки це робить весь додаток нестабільним. Наприклад, після того, як було зафіксовано близько 10 помилок ECONNRESET, сервер іноді став невідповідним (просто заморозив і не мав будь-яких з'єднань)
додано Автор Samson, джерело

Така ж проблема була сьогодні. Після деяких досліджень я виявив дуже корисний - abort-on-uncaught-exception node.js . Він не тільки забезпечує набагато більш детальну та корисну трасу стеку помилок, але також зберігає основний файл при збої програми, що дозволяє подальше налагодження.

12
додано
Дивно, що нова відповідь на це старе питання повинна з'явитися, як я шукаю - але це чудово, спасибі
додано Автор Semicolon, джерело

Я зіткнувся з тим же питанням, але я пом'якшив це, розмістивши:

server.timeout = 0;

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

11
додано
Це не рішення, а скоріше швидкий виправлення, яке розбиває речі, не викидаючи помилки.
додано Автор Nishant Ghodke, джерело

Так, ваша служба політичного файлу може без сумніву призвести до аварії.

Щоб повторити, просто додайте затримку до вашого коду:

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() { console.log("error"); });
  socket.write("<?xml version=\"1.0\"?>\n")

Коли ви спробуєте звернутись вище, ви просто отримаєте повідомлення журналу, а не аварійне завершення роботи.

А коли ви закінчите, не забудьте видалити затримку.

6
додано

Іншим можливим випадком (але рідко) може бути, якщо у вас є сервер-зв'язок із сервером, і встановіть server.maxConnections до дуже низького значення.

У базовому вузлі lib net.js це буде викликати clientHandle.close() , що також призведе до помилки ECONNRESET:

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

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

Це дивно, але він працював для мене, тепер я ще не бачу помилку ECONNRESET.

1
додано

Я також мав цю помилку і зміг вирішити її після декількох днів налагодження та аналізу:

моє рішення

Для мене VirtualBox (для Docker) була проблемою. У Port Forwarding налаштовано на моєму VM, і помилка виникла лише на переадресованому порту.

загальні висновки

Наступні спостереження можуть заощадити дні роботи, які я мав інвестувати:

  • For me the problem only occurred on connections from localhost to localhost on one port. -> check changing any of these constants solves the problem.
  • For me the problem only occurred on my machine -> let someone else try it.
  • For me the problem only occurred after a while and couldn't be reproduced reliably
  • My Problem couldn't be inspected with any of nodes or expresses (debug-)tools. -> don't waste time on this

-> figure out if something is messing around with your network (-settings), like VMs, Firewalls etc., this is probably the cause of the problem.

1
додано

Я вирішив проблему, просто підключившись до іншої мережі . Це одна з можливих проблем.

Як вже було сказано вище, ECONNRESET означає, що розмова TCP різко закрила свій кінець з'єднання.

Ваше інтернет-з'єднання може блокувати підключення до деяких серверів. У моєму випадку я намагався підключитися до mLab (служби хмарних баз даних, на яких розміщуються бази даних MongoDB). І мій інтернет-провайдер блокує його.

1
додано
Цей працював для мене, мій код, який працював чудово кілька годин назад, раптово перестав працювати, виявляється, зміна мережі викликала проблему
додано Автор Aklank Jain, джерело

Спробуйте додати ці параметри до socket.io:

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

Я сподіваюсь, це допоможе вам!

0
додано
dev-ua/node
dev-ua/node
1 122 учасників

Chat for Node.js developers. We love other non-frontend JS environments too!