मैं नोड.जेएस को दुर्घटनाग्रस्त होने से कैसे रोकूं? कोशिश-कैच काम नहीं करता है


157

मेरे अनुभव से, एक php सर्वर लॉग या सर्वर के अंत के लिए एक अपवाद को फेंक देगा, लेकिन नोड.जेएस बस दुर्घटनाग्रस्त हो जाता है। एक कोशिश के साथ मेरे कोड को घेरना या तो काम नहीं करता है क्योंकि सब कुछ अतुल्यकालिक रूप से किया जाता है। मैं जानना चाहूंगा कि हर कोई अपने उत्पादन सर्वर में क्या करता है।

जवाबों:


132

अन्य उत्तर वास्तव में पागल हैं जैसा कि आप नोड के स्वयं के दस्तावेजों में http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception पर पढ़ सकते हैं

यदि कोई अन्य बताए गए उत्तरों का उपयोग कर रहा है, तो नोड डॉक्स पढ़ें:

ध्यान दें कि uncaughtExceptionअपवाद से निपटने के लिए एक बहुत ही कच्चा तंत्र है और भविष्य में इसे हटाया जा सकता है

PM2

सबसे पहले, मैं अत्यधिक के PM2लिए स्थापित करने की सलाह दूंगा Node.js। PM2 क्रैश से निपटने और नोड एप्लिकेशन के साथ-साथ लोड संतुलन की निगरानी करने में वास्तव में बहुत अच्छा है। PM2 तुरंत जब भी क्रैश होता है तो नोड ऐप शुरू करता है, किसी भी कारण से रुकता है या सर्वर के पुनरारंभ होने पर भी। इसलिए, अगर किसी दिन हमारे कोड को प्रबंधित करने के बाद भी, ऐप क्रैश हो जाता है, तो PM2 इसे तुरंत पुनः आरंभ कर सकता है। अधिक जानकारी के लिए, इंस्टॉल करना और PM2 चलाना

अब एप्लिकेशन को दुर्घटनाग्रस्त होने से बचाने के लिए हमारे समाधान पर वापस आ रहा है।

इसलिए अंत में जाने के बाद मैं अंत में स्वयं के साथ क्या दस्तावेज लेकर आया था:

का प्रयोग न करें uncaughtException, उपयोग domainsके साथ clusterबजाय। यदि आप उपयोग करते हैं uncaughtException, तो हर खंडित अपवाद के बाद अपने आवेदन को फिर से शुरू करें!

क्लस्टर के साथ DOMAIN

हम वास्तव में क्या करते हैं, उस त्रुटि के लिए एक प्रतिक्रिया भेजते हैं जो त्रुटि को ट्रिगर करता है, जबकि दूसरों को उनके सामान्य समय में खत्म करने देता है, और उस कार्यकर्ता में नए अनुरोधों को सुनना बंद कर देता है।

इस तरह, डोमेन उपयोग क्लस्टर मॉड्यूल के साथ हाथ से हाथ जाता है, क्योंकि मास्टर प्रक्रिया एक कार्यकर्ता को एक त्रुटि होने पर एक नए कार्यकर्ता को कांटा कर सकती है। मेरे कहने का मतलब समझने के लिए नीचे दिया गया कोड देखें

का उपयोग करके Domain, और हमारे कार्यक्रम को कई कार्यकर्ता प्रक्रियाओं में उपयोग करने की लचीलापन Cluster, हम अधिक उचित प्रतिक्रिया कर सकते हैं, और बहुत अधिक सुरक्षा के साथ त्रुटियों को संभाल सकते हैं।

var cluster = require('cluster');
var PORT = +process.env.PORT || 1337;

if(cluster.isMaster) 
{
   cluster.fork();
   cluster.fork();

   cluster.on('disconnect', function(worker) 
   {
       console.error('disconnect!');
       cluster.fork();
   });
} 
else 
{
    var domain = require('domain');
    var server = require('http').createServer(function(req, res) 
    {
        var d = domain.create();
        d.on('error', function(er) 
        {
            //something unexpected occurred
            console.error('error', er.stack);
            try 
            {
               //make sure we close down within 30 seconds
               var killtimer = setTimeout(function() 
               {
                   process.exit(1);
               }, 30000);
               // But don't keep the process open just for that!
               killtimer.unref();
               //stop taking new requests.
               server.close();
               //Let the master know we're dead.  This will trigger a
               //'disconnect' in the cluster master, and then it will fork
               //a new worker.
               cluster.worker.disconnect();

               //send an error to the request that triggered the problem
               res.statusCode = 500;
               res.setHeader('content-type', 'text/plain');
               res.end('Oops, there was a problem!\n');
           } 
           catch (er2) 
           {
              //oh well, not much we can do at this point.
              console.error('Error sending 500!', er2.stack);
           }
       });
    //Because req and res were created before this domain existed,
    //we need to explicitly add them.
    d.add(req);
    d.add(res);
    //Now run the handler function in the domain.
    d.run(function() 
    {
        //You'd put your fancy application logic here.
        handleRequest(req, res);
    });
  });
  server.listen(PORT);
} 

हालाँकि Domain, लंबित वंचित है और हटा दिया जाएगा क्योंकि नए प्रतिस्थापन के रूप में नोड के प्रलेखन में कहा गया है

यह मॉड्यूल अपग्रेडेशन लंबित है। एक बार एक प्रतिस्थापन एपीआई को अंतिम रूप देने के बाद, यह मॉड्यूल पूरी तरह से समाप्त हो जाएगा। उपयोगकर्ता जो पूरी तरह से कार्यक्षमता है कि डोमेन प्रदान करते हैं उस समय के लिए उस पर भरोसा कर सकते हैं, लेकिन भविष्य में एक अलग समाधान के लिए पलायन करने की उम्मीद करनी चाहिए।

लेकिन जब तक नया प्रतिस्थापन नहीं लाया जाता है, तब तक क्लस्टर के साथ डोमेन एकमात्र अच्छा समाधान है जो नोड डॉक्यूमेंटेशन बताता है।

गहराई से समझने Domainऔर Clusterपढ़ने के लिए

https://nodejs.org/api/domain.html#domain_domain (Stability: 0 - Deprecated)

https://nodejs.org/api/cluster.html

क्लस्टर और डोमेन पर इस अद्भुत इन-डेप्थ स्पष्टीकरण को साझा करने के लिए @ स्टेनली लुओ का धन्यवाद

क्लस्टर और डोमेन


9
चेतावनी का एक शब्द, डोमेन लंबित है: लिंक । नोड डॉक्स से सुझाई गई विधि, क्लस्टर: लिंक का उपयोग करना है ।
पॉल

4
restart your application after every unhandled exception!मामले में 2000 उपयोगकर्ता वीडियो स्ट्रीमिंग के लिए एक नोड वेब सर्वर का उपयोग कर रहे हैं और 1 उपयोगकर्ता को एक अपवाद मिला है तो पुनः आरंभ करने से अन्य सभी उपयोगकर्ता बाधित नहीं होंगे?
विकास बंसल

2
@VikasBansal हाँ जो निश्चित रूप से सभी उपयोगकर्ताओं को बाधित करेगा और इसलिए इसके बजाय uncaughtExceptionइसका उपयोग और उपयोग Domainकरना बुरा है Cluster, यदि कोई उपयोगकर्ता अपवाद का सामना करता है, तो केवल उसके धागे को क्लस्टर से हटा दिया जाता है और उसके लिए नया बनाया जाता है। और आपको अपने नोड सर्वर को भी पुनरारंभ करने की आवश्यकता नहीं है। जबकि दूसरी तरफ अगर आप इसका उपयोग करते हैं तो आपको uncaughtExceptionहर बार अपने सर्वर को फिर से शुरू करना होगा ताकि आपके किसी भी उपयोगकर्ता को समस्या का सामना करना पड़े। इसलिए, क्लस्टर के साथ डोमेन का उपयोग करें।
हवादार

3
domainपूरी तरह से पदावनत और हटाए जाने पर हमें क्या करना चाहिए ?
जस

3
इस ट्यूटोरियल को उन लोगों के लिए पाया गया, जो कि clusterऔर workers: sitepoint.com/-
स्टेनली लुओ

81

मैंने अपने आवश्यकता बयानों और वैश्विक घोषणाओं के तहत इस कोड को सही रखा:

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

मेरे लिये कार्य करता है। केवल एक चीज जो मुझे पसंद नहीं है, वह यह है कि मुझे उतनी जानकारी नहीं मिल रही है जितनी कि अगर मैं इस चीज को दुर्घटनाग्रस्त कर दूं।


45
सावधानी का एक शब्द: यह विधि अच्छी तरह से काम करती है, लेकिन याद रखें कि सभी HTTP प्रतिक्रियाओं को ठीक से समाप्त करने की आवश्यकता है। इसका मतलब है कि यदि आप HTTP अनुरोध को हैंडल करते समय कोई अनकहा अपवाद नहीं होता है, तो आपको अभी भी http.ServerResponse ऑब्जेक्ट पर अंत () कॉल करना होगा। हालाँकि आप इस पर अमल करते हैं। यदि आप ऐसा नहीं करते हैं, तो ब्राउज़र लटका देने तक अनुरोध लटका रहेगा। यदि आपके पास इन अनुरोधों में से पर्याप्त है, तो सर्वर मेमोरी से बाहर चला सकता है।
बीएमएनर

3
@ बीएमएनआर, क्या आप एक बेहतर कार्यान्वयन प्रदान कर सकते हैं? मैंने इस समस्या पर ध्यान दिया (हैंग करने का अनुरोध) तो यह वास्तव में सर्वर foreverया कुछ का उपयोग करने से बेहतर है।
पिक्सफ्रीक

6
यह एक गहन व्याख्या के लिए कहता है। मुझे पता है कि यह बेकार है, लेकिन जब भी कोई अनकहा अपवाद होता है, तो आपके सर्वर को ASAP को रिबूट करने की आवश्यकता होती है। वास्तव में, 'अनक्रेडएक्ससेप्शन' ईवेंट का उद्देश्य चेतावनी ईमेल भेजने के अवसर के रूप में इसका उपयोग करना है, और फिर प्रक्रिया का उपयोग करें। एक्सिट (1); सर्वर को बंद करने के लिए। आप सर्वर को पुनः आरंभ करने के लिए हमेशा के लिए या ऐसा कुछ उपयोग कर सकते हैं। HTTP लंबित कोई भी अनुरोध टाइमआउट और विफल हो जाएगा। आपके उपयोगकर्ता आप पर पागल हो जाएंगे। लेकिन, इसका सबसे अच्छा समाधान है। तुम क्यों पूछते हो? Checkout stackoverflow.com/questions/8114977/…
बीएमनर

3
अनकैप्ड त्रुटि से अधिक जानकारी प्राप्त करने के लिए, उपयोग करें: कंसोल.ट्रेस (इरेटास्टैक);
जेसी डनलप

2
चेतावनी: नोड के लिए प्रलेखन कहते हैं, कोई अनिश्चित मामले में, यह है कि आप के रूप में यह के पागल खतरनाक यह कभी नहीं करना चाहिए: nodejs.org/api/process.html#process_event_uncaughtexception
जेरेमी लोगान

28

जैसा कि यहां बताया गया है कि आपको error.stackअधिक पूर्ण त्रुटि संदेश प्रदान करना होगा जैसे कि लाइन नंबर जो त्रुटि का कारण बना:

process.on('uncaughtException', function (error) {
   console.log(error.stack);
});

12

प्रयत्न supervisor

npm install supervisor
supervisor app.js

या आप foreverइसके बजाय स्थापित कर सकते हैं ।

यह सब आपके सर्वर को पुनर्प्राप्त करने के बाद क्रैश होने पर करेगा।

forever कोड के भीतर इस्तेमाल किया जा सकता है इनायत किसी भी प्रक्रिया है कि दुर्घटना को ठीक करने के लिए।

foreverडॉक्स बाहर निकलें / त्रुटि प्रोग्राम के रूप में से निपटने पर ठोस जानकारी नहीं है।


9
निश्चित रूप से यह समाधान नहीं हो सकता है ... जिस समय सर्वर डाउन होता है उस समय में यह नए आने वाले अनुरोधों का जवाब नहीं दे सकता है। एप्लिकेशन कोड से एक अपवाद को फेंक दिया जा सकता है - सर्वर को 500 त्रुटि के साथ जवाब देने की आवश्यकता है, न कि केवल क्रैश और इसके पुनः आरंभ होने की उम्मीद है।
एंट कुटेसरा

20
एक हैकर के रूप में, कोई यह पता लगा सकता है कि उन्हें सर्वर को एक सरल अनुरोध भेजने और एक अनुरोध पैरामीटर को याद करने की आवश्यकता है - जो कि जावास्क्रिप्ट में एक अपराजित की ओर जाता है जो नोड.जेएस को दुर्घटना का कारण बनता है। आपके सुझाव से मैं आपके पूरे समूह को बार-बार मार सकता हूं। इसका उत्तर यह है कि एप्लिकेशन को इनायत से विफल बना दिया जाए - यानी बिना किसी अपवाद के संभालें और दुर्घटनाग्रस्त न हों। क्या होगा अगर सर्वर कई वीओआइपी सत्रों को संभाल रहा है? यह दुर्घटना और जलने के लिए और उन सभी मौजूदा सत्रों के लिए इसके साथ मरने के लिए स्वीकार्य नहीं है। आपके उपयोगकर्ता जल्द ही छोड़ देंगे।
एंट कुटसेरा

5
@AntKutschera यही कारण है कि अपवाद असाधारण मामले होने चाहिए। अपवाद केवल उन स्थितियों में आग लगाने चाहिए जहां आप ठीक नहीं हो सकते हैं और जहां प्रक्रिया को क्रैश करना पड़ता है। इन असाधारण मामलों को संभालने के लिए आपको अन्य साधनों का उपयोग करना चाहिए । लेकिन मैं आपकी बात देखता हूँ। जहां संभव हो आप इनायत करें। हालांकि ऐसे मामले जहां भ्रष्ट राज्य के साथ जारी रहने से अधिक नुकसान होगा।
रेयानोस

2
हाँ, यहाँ विचार के विभिन्न स्कूल हैं। जिस तरह से मैंने इसे सीखा (जावास्क्रिप्ट के बजाय जावा) वहाँ स्वीकार्य विस्तार हैं जो आपको उम्मीद करनी चाहिए, शायद व्यापारिक अपवाद के रूप में जाना जाता है, और फिर रनटाइम अपवाद या त्रुटियां हैं, जहां आपको पुनर्प्राप्त करने की उम्मीद नहीं करनी चाहिए, जैसे मेमोरी से बाहर। शालीनता से असफल नहीं होने के साथ एक समस्या यह है कि कुछ पुस्तकालय जो मैं लिखता हूं वह यह घोषित कर सकता है कि यह कुछ पुनर्प्राप्त करने के मामले में एक अपवाद फेंकता है, यह कहना है कि जहां उपयोगकर्ता अपने इनपुट को सही कर सकता है। अपने ऐप में, आपने मेरे डॉक्स नहीं पढ़े और बस दुर्घटनाग्रस्त हो गई, जहाँ उपयोगकर्ता शायद ठीक हो गया हो
Ant Kutschera

1
@AntKutschera यही कारण है कि हम अपवादों को लॉग करते हैं। आपको सामान्य अपवादों के लिए अपने उत्पादन लॉग का विश्लेषण करना चाहिए, और यह पता लगाना चाहिए कि क्या और कैसे आप उनसे ठीक हो सकते हैं, बजाय सर्वर को क्रैश करने के। मैंने PHP, रूबी ऑन रेल्स, और नोड के साथ उस पद्धति का उपयोग किया है। भले ही आप एक प्रक्रिया से बाहर निकलें या नहीं, हर बार जब आप 500 त्रुटि को फेंक देते हैं, तो आप अपने उपयोगकर्ताओं को एक सेवा कर रहे हैं। यह जावास्क्रिप्ट या नोड-विशिष्ट अभ्यास नहीं है।
एरिक इलियट

7

ट्राई-कैच के प्रयोग से अनकैप्ड एरर को हल किया जा सकता है, लेकिन कुछ जटिल परिस्थितियों में, यह सही काम नहीं करेगा जैसे कि async फंक्शन को पकड़ना। याद रखें कि Node में, किसी भी async फ़ंक्शन कॉल में संभावित ऐप क्रैश ऑपरेशन हो सकता है।

उपयोग करना uncaughtExceptionएक वर्कअराउंड है, लेकिन इसे अक्षम के रूप में मान्यता प्राप्त है और इसे नोड के भविष्य के संस्करणों में हटाए जाने की संभावना है, इसलिए इस पर भरोसा न करें।

डोमेन का उपयोग करने के लिए आदर्श समाधान है: http://nodejs.org/api/domain.html

यह सुनिश्चित करने के लिए कि आपका ऐप अप हो रहा है और आपका सर्वर भी दुर्घटनाग्रस्त हो रहा है, निम्न चरणों का उपयोग करें:

  1. प्रति कोर कई प्रक्रिया कांटा करने के लिए नोड क्लस्टर का उपयोग करें। इसलिए यदि एक प्रक्रिया की मृत्यु हो गई, तो एक अन्य प्रक्रिया ऑटो बूट अप होगी। देखें: http://nodejs.org/api/cluster.html

  2. कोशिश-कैच या अनकैप्ड का उपयोग करने के बजाय async ऑपरेशन को पकड़ने के लिए डोमेन का उपयोग करें। मैं यह नहीं कह रहा हूं कि ट्राइ-कैच या अनकैप्ड बुरा विचार है!

  3. अपनी सेवाओं की निगरानी के लिए हमेशा के लिए / पर्यवेक्षक का उपयोग करें

  4. अपने नोड ऐप को चलाने के लिए डेमन जोड़ें: http://upstart.ubuntu.com

उम्मीद है की यह मदद करेगा!


4

Pm2 नोड मॉड्यूल के लिए एक प्रयास दें यह अभी तक सुसंगत है और इसमें महान दस्तावेज हैं। Node.js ऐप्स के लिए उत्पादन प्रक्रिया प्रबंधक बिल्ट-इन लोड बैलेंसर के साथ है। कृपया इस समस्या के लिए किसी अपवाद से बचें। https://github.com/Unitech/pm2


`हर अनकहे अपवाद के बाद अपने आवेदन को पुनः आरंभ करें!` यदि 2000 उपयोगकर्ता वीडियो स्ट्रीमिंग के लिए नोड वेब सर्वर का उपयोग कर रहे हैं और 1 उपयोगकर्ता को अपवाद मिला है तो पुनः आरंभ करने से अन्य सभी उपयोगकर्ता बाधित नहीं होंगे?
विकास बंसल

मैं बहुत खुश था जब मैंने पीएम 2 की खोज की। सॉफ्टवेयर का एक बड़ा टुकड़ा
Mladen Janjetovic

0

अनएडिसएक्स अपवाद "एक बहुत ही क्रूड तंत्र" (इतना सच) है और डोमेन अब हटाए गए हैं। हालाँकि, हमें अभी भी (तार्किक) डोमेन के आसपास त्रुटियों को पकड़ने के लिए कुछ तंत्र की आवश्यकता है। पुस्तकालय:

https://github.com/vacuumlabs/yacol

ऐसा करने में आपकी मदद कर सकता है। थोड़ा अतिरिक्त लेखन के साथ आप अपने कोड के चारों ओर अच्छा डोमेन शब्दार्थ कर सकते हैं!


0

बहाल करने पर महान काम करता है:

server.on('uncaughtException', function (req, res, route, err) {
  log.info('******* Begin Error *******\n%s\n*******\n%s\n******* End Error *******', route, err.stack);
  if (!res.headersSent) {
    return res.send(500, {ok: false});
  }
  res.write('\n');
  res.end();
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.