ECONNRESET hatası Node.js'de nasıl hata ayıklayabilirim?


288

Bir sohbet web uygulaması için Socket.io kullanarak bir Express.js uygulaması çalıştırıyorum ve 24 saat boyunca rastgele yaklaşık 5 kez aşağıdaki hatayı alıyorum. Düğüm süreci sonsuza kadar sarılır ve hemen kendini yeniden başlatır.

Sorun şu ki, Express'i yeniden başlatmak kullanıcılarımı odalarından çıkarıyor ve kimse bunu istemiyor.

Web sunucusu HAProxy tarafından proxy uygulanmıştır. Sadece websockets ve flashsockets aktarımlarını kullanan soket kararlılığı sorunları yoktur. Bunu bilerek çoğaltamıyorum.

Düğümdeki hata 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

DÜZENLE (2013-07-22)

Hem socket.io istemci hatası işleyicisi hem de yakalanmayan özel durum işleyicisi eklendi. Bunun hatayı yakaladığı anlaşılıyor:

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

Bu yüzden bunun bir Socket.io sorunu değil, yaptığım başka bir sunucuya HTTP isteği veya MySQL / Redis bağlantısı olduğundan şüpheleniyorum. Sorun, hata yığınının kod sorunumu tanımama yardımcı olmamasıdır. Günlük çıktısı:

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

Buna neyin sebep olduğunu nasıl bilebilirim? Hatadan nasıl daha fazla yararlanabilirim?

Tamam, çok ayrıntılı değil ama işte Longjohn ile olan yığın takibi:

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

İşte ben flaş soket ilke dosyası hizmet:

    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)

Sebep bu olabilir mi?


3
@GottZ belki bu yardımcı olabilir (js düğümünde çalışan biriyle konuştu) gist.github.com/samsonradu/1b0c6feb438f5a53e30e . Bugün socket.error handler'ı dağıtacağım ve size bildireceğim.
Samson

1
@ Socket.error handles yardımcı olmaz, ancak process.on ('uncaughtException') hatayı yakalar. İşte hatanın console.log'u: {[Hata: ECONNRESET'i okuyun] kodu: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read'}
Samson

1
ECONNRESET ağ sorunundan kaynaklanıyor olabilir. Bildiğiniz gibi, test yaparken tüm istisnaları yakalamak imkansızdır. Bazıları üretim sunucunuzda görünecektir. Sunucunuzu sağlam yapmanız gerekecek. Depolama olarak Redis'i kullanarak oturum silme işlemini gerçekleştirebilirsiniz. Düğüm sunucunuz çöktükten sonra bile oturumlarınızın kalıcı olmasını sağlar.
user568109

1
Bu neden oturum silme ile ilgilidir? Zaten Redis tarafından ele alınırlar.
Samson

3
İşleyici ayarlanmamış en az bir TCP soketiniz var. Şimdi bunun nerede olduğunu kontrol etme zamanı: D
Moss

Yanıtlar:


253

Bunu önceden tahmin etmiş olabilirsiniz: bu bir bağlantı hatasıdır.

"ECONNRESET" TCP konuşmasının diğer tarafının aniden bağlantının sonunu kapatması anlamına gelir. Bunun nedeni büyük olasılıkla bir veya daha fazla uygulama protokolü hatasıdır. Bir şeyden şikayet edip etmediğini görmek için API sunucusu günlüklerine bakabilirsiniz.

Ama aynı zamanda sorun hata ayıklama potansiyel hatayı kontrol etmek için bir yol arıyoruz beri, sen bakmak gerekir " Bir yuva NodeJS? Hatayı asmak hata ayıklamak için nasıl " bir benzeri soruya ilişkin olarak stackoverflow yayınlanmıştır.

Geliştirme için hızlı ve kirli çözüm :

Longjohn kullanın , zaman uyumsuz işlemleri içeren uzun yığın izleri alırsınız.

Temiz ve doğru çözüm : Teknik olarak, düğümde, bir 'error'olay yayarsanız ve kimse onu dinlemediğinde, o atacaktır . Atmamasını sağlamak için üzerine bir dinleyici koyun ve kendiniz halledin. Bu şekilde hatayı daha fazla bilgi ile kaydedebilirsiniz.

Bir grup çağrı için bir dinleyiciye sahip olmak için etki alanlarını kullanabilir ve çalışma zamanında diğer hataları da yakalayabilirsiniz. Http (Sunucu / İstemci) ile ilgili her eşzamansız işlemin , kodun diğer bölümlerine kıyasla farklı etki alanı bağlamında olduğundan emin olun ; etki alanı otomatik olarak errorolayları dinler ve bunu kendi işleyicisine yayar. Böylece sadece bu işleyiciyi dinler ve hata verilerini alırsınız. Ayrıca ücretsiz olarak daha fazla bilgi edinebilirsiniz.

DÜZENLE (2013-07-22)

Yukarıda yazdığım gibi:

"ECONNRESET" TCP konuşmasının diğer tarafının aniden bağlantının sonunu kapatması anlamına gelir. Bunun nedeni büyük olasılıkla bir veya daha fazla uygulama protokolü hatasıdır. Bir şeyden şikayet edip etmediğini görmek için API sunucusu günlüklerine bakabilirsiniz.

Ne de olabilir: rastgele zamanlarda, diğer taraf aşırı yüklenir ve sonuç olarak bağlantıyı basitçe öldürür. Bu durumda, tam olarak neye bağlandığınıza bağlıdır…

Ama kesin olan bir şey var: TCP bağlantınızda istisnaya neden olan bir okuma hatası var. Bunu, düzenlemenizde yayınladığınız ve onaylayan hata koduna bakarak görebilirsiniz.


'Aniden kapalı' anlamına gelmek zorunda değil. Genellikle yazıdan, eşin zaten normal olarak kapattığı bir bağlantıya neden olur. Bu bir RST vermesine neden olacaktır.
Lorne Marquis

1
@EJP “Aniden” yazmamın iyi bir nedeni vardı. Hata (uyarı değil), bağlantının eş tarafından sıfırlandığını belirtir. Mevcut bir bağlantı, uzak eş tarafından zorla kapatıldı. Zorla kapama beklenmedik bir aniden beri! (Bu normalde, uzak makinedeki eş uygulaması aniden durdurulursa, makine yeniden başlatılırsa veya eş uygulaması uzak yuvada "sabit kapanma" kullanırsa ortaya çıkar. Bu hata, "canlı tutma" etkinliği nedeniyle bir bağlantı kopması durumunda da ortaya çıkabilir bir veya daha fazla işlem yapılırken bir arıza tespit edildiğinde… bu işlemler ve müteakip işlemler başarısız olacaktır.)
e-sushi

2
Test için tarayıcıdan (Chrome) eşzamanlı olarak yaklaşık 100 API çağrısı toplu olarak gönderirken bu hatayı atarım. Chrome'un daha sonra aşırı yüklenmiş olması ve bağlantıların bazılarını öldürmesi gerektiğini hayal ediyorum ...
supershnee

2
@supershnee Verileriniz, uygulamanız ve node.js'nin kendisi bilinmeyen bir durumda olduğundan, yakalanmamış bir kural dışı durumdan sonra sunucunuzu neredeyse her zaman yeniden başlatmalısınız. Bir istisnadan sonra devam etmek verilerinizi riske atar. Daha fazla bilgi edinmek isterseniz , işlemdeki Düğümün belgelerine veya etki alanlarındaki Düğümün belgelerine bakın .
c1moore

39

Flash ilke dosyasını sunmak için sahip olduğum basit bir tcp sunucusu buna neden oluyordu. Şimdi bir işleyici kullanarak hatayı yakalayabilirim:

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

2
Kodda yanlış bir şey var mı? Yazmadan önce soketin yazılabilir olup olmadığını kontrol etmeliydim?
Samson

Doh, hemen hemen aynı şeyi göndermeden önce çözümü bulduğunu görmedim :) Sorunuza gelince, soketin yazılabilir olduğunu kontrol etseniz bile, mikrosaniye sonra yazdığınızda olmayabilir ve yine de bir hata verir, bu yüzden emin olmak için "yol" budur.
Joachim Isaksson

tamam, ve eğer güvenli bir çıkış yolu var mı? hata işleyicisinin içindeki socket.close () gibi mi? çünkü bu hatalardan sonra CPU yükümün arttığını düşünüyorum (emin değilim)
Samson

2
socket.destroy()Emin olmak için her zaman hata işleyicisini aradım . Ne yazık ki gerekli olup olmadığını belgeler bulamıyorum, ancak bunu yapmak için bir hata yaymaz.
Joachim Isaksson

socket.destroy () ne olursa olsun günümü kurtardı !! Teşekkür ederim!
Firas Abd Alrahman

27

Düğüm yükseltmesinden sonra uygulamaların hata vermeye başladığı benzer bir sorun yaşadım. Bunun Düğüm sürümü v0.9.10'a kadar izlenebileceğine inanıyorum:

  • net: ECONNRESET'i (Ben Noordhuis) bastırmayın

Önceki sürümler istemciden kaynaklanan kesintilerde hata vermiyordu. İstemciden bağlantı kopması, düğümde ECONNRESET hatasını atar. Bunun Düğüm için işlevsellik olduğuna inanıyorum, bu yüzden düzeltme (en azından benim için), yakalanmayan istisnalarda yaptığınıza inandığım hatayı ele almaktı. Her ne kadar ben net.socket handler.

Bunu gösterebilirsiniz:

Basit bir soket sunucusu yapın ve Düğüm v0.9.9 ve v0.9.10'u edinin.

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

V0.9.9 kullanarak başlatın ve ardından bu sunucuya FTP göndermeyi deneyin. FTP ve 21 numaralı bağlantı noktasını yalnızca Windows kullanıyorum ve bir FTP istemcim olduğu için kullanıyorum, ancak telnet istemcisi kullanışlı değil.

Sonra istemci tarafından bağlantıyı kesmeniz yeterlidir. (Sadece Ctrl-C yapıyorum)

V0.9.9 Düğümü kullanılırken HATA YOK ve v.0.9.10 Düğümü ve üstü kullanılırken HATA görmelisiniz.

Üretimde v.0.10 kullanıyorum. bir şey ve hala hata veriyor. Yine, bunun amaçlandığını ve çözüm kodunuzdaki hatayı işlemek olduğunu düşünüyorum.


3
Teşekkürler, kendim çiviledim! Tüm uygulamayı kararsız hale getirdiği için hataların uncaughtException'a yayılmasına izin vermemek önemlidir. Örneğin, yaklaşık 10 ECONNRESET hatası yakaladıktan sonra sunucu bazen yanıt vermiyordu (sadece dondu ve herhangi bir bağlantıyı işlemedi)
Samson

Ayrıca hatayı artık baskılamayan düğüm sürümü değişikliğini biliyordu, ancak her sürümü gösteren ve çözülen pek çok sorunu görüyorum, en sonuncuyu tercih ediyorum. V0.10.13 şimdi btw kullanıyorum
Samson

16

Bugün de aynı problem vardı. Bazı araştırmalardan sonra çok kullanışlı bir --abort-on-uncaught-exceptionnode.js seçeneği buldum . Sadece çok daha ayrıntılı ve kullanışlı hata yığını izleme sağlamakla kalmaz, aynı zamanda çekirdek dosyayı uygulama çökmesine kaydederek daha fazla hata ayıklamaya izin verir.


4
Bu eski soruya yeni bir cevabın baktığımda ortaya çıkması garip - ama bu harika, teşekkürler
Semicolon

13

Aynı sorunla karşı karşıya kaldım, ancak şunları yaparak hafiflettim:

server.timeout = 0;

önce server.listen. serverburada bir HTTP sunucusudur. API belgelerine göre varsayılan zaman aşımı 2 dakikadır .


5
Bu bir çözüm değil, hata atmadan işleri bozacak bir düzeltme.
Nishant Ghodke

9

Başka bir olası durum (ancak nadir), sunucudan sunucuya iletişiminiz varsa ve server.maxConnectionsçok düşük bir değere ayarlanmış olmanız olabilir.

Düğümün çekirdek lib olarak net.js çağıracağı clientHandle.close()hangi da hata ECONNRESET neden olacak:

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

Büyük çağrı, ancak maxConnectionsvarsayılan değer Infinity. Bu değeri (söylediğin gibi) yalnızca bu değeri açıkça geçersiz kıldığınızda olur.
Gajus

7

Evet, ilke dosyasını sunmanız kesinlikle çökmeye neden olabilir.

Tekrarlamak için kodunuza bir gecikme eklemeniz yeterlidir:

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

… Ve telnetbağlantı noktasına bağlanmak için kullanın . Gecikme süresi dolmadan telnet bağlantısını keserseniz, socket.write hata verdiğinde bir kilitlenme (yakalanmayan istisna) alırsınız.

Buradaki kilitlenmeyi önlemek için soketi okumadan / yazmadan önce bir hata işleyici ekleyin:

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

Yukarıdaki bağlantıyı kesmeyi denediğinizde, çökme yerine bir günlük iletisi alırsınız.

Ve işiniz bittiğinde, gecikmeyi kaldırmayı unutmayın.


6

Ayrıca, benim gelişimi sırasında bunun gereğidir çözmek yol ECONNRESET hatası alıyorum değil sadece kullanmak, benim sunucuyu başlatmak için nodemon kullanarak "node server.js"benim sunucu benim sorunum sabit başlatın.

Garip, ama benim için çalıştı, şimdi ECONNRESET hatasını bir daha asla göremiyorum.


4

Bu hatayı da aldım ve hata ayıklama ve analiz günlerinden sonra çözmeyi başardım:

çözümüm

Benim için sorun VirtualBox (Docker için) idi. VM'imde Port Yönlendirme yapılandırılmıştı ve hata sadece iletilen portta meydana geldi.

genel sonuçlar

Aşağıdaki gözlemler size yatırım yapmak zorunda olduğum günlerce çalışma tasarrufu sağlayabilir:

  • Benim için sorun sadece bir bağlantı noktasındaki localhost ile localhost arasındaki bağlantılarda meydana geldi. -> Bu sabitlerden herhangi birinin değiştirilmesinin sorunu çözüp çözmediğini kontrol edin.
  • Benim için sorun sadece makinemde meydana geldi -> başkasının denemesine izin ver.
  • Benim için sorun sadece bir süre sonra ortaya çıktı ve güvenilir bir şekilde çoğaltılamadı
  • Sorunum hiçbir düğüm veya ifade (hata ayıklama) aracıyla denetlenemedi. -> bu konuda zaman kaybetmeyin

-> VM'ler, Güvenlik duvarları vb. gibi ağınızla (ayarlar) karışan bir şey olup olmadığını anlayın, muhtemelen sorunun nedeni budur.


2

Sorunu sadece farklı bir ağa bağlanarak çözdüm . Olası sorunlardan biri bu.

Yukarıda tartışıldığı gibi, ECONNRESET , TCP görüşmesinin bağlantının sonunu aniden kapattığı anlamına gelir.

İnternet bağlantınız bazı sunuculara bağlanmanızı engelliyor olabilir. Benim durumumda, mLab (MongoDB veritabanlarını barındıran bulut veritabanı hizmeti) bağlanmaya çalışıyordum. Ve ISS'm bunu engelliyor.


Bu benim için çalıştı, birkaç saat önce iyi çalışan kodum aniden çalışmayı durdurdu, ağ değişikliği soruna neden oldu
Aklank Jain

2

Bu sorunu şu şekilde çözmüştüm:

  • Wifi / ethernet bağlantımı kapatıp açın.
  • Ben npm updatenpm güncellemek için terminalde yazdım.
  • Oturumdan çıkıp tekrar giriş yapmayı denedim

Bundan sonra aynı npm komutunu denedim ve iyi bir şey çalıştı. Bu kadar basit olduğundan emin değildim.

CENTOS 7 kullanıyorum


0

Aynı sorunu vardı ve sorun Node.js sürümü olduğu anlaşılıyor.

Node.js'nin önceki sürümünü (10.14.2) yükledim ve her şey nvm kullanarak tamamdı (Node.js'nin birkaç sürümünü yüklemenize ve hızlı bir şekilde bir sürümden diğerine geçmenize izin verin).

Bu "temiz" bir çözüm değildir, ancak size geçici olarak hizmet edebilir.


0

En azından kullanım durumumda bunu anladım.

Başlıyordum ECONNRESET. İstemcimin kurulum şekli, sunucuya bir API çağrısı ile tonlarca gerçekten hızlı bir şekilde çarptığı ortaya çıktı - ve sadece bir kez uç noktaya ulaşması gerekiyordu.

Bunu düzelttiğimde hata gitti.


-2

Bu seçenekleri socket.io dosyasına eklemeyi deneyin:

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

Umarım bu sana yardımcı olmuştur !

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.