Comment puis-je empêcher nœud.js à partir de la plante? try-catch ne fonctionne pas

D'après mon expérience, un serveur php lancerait une exception à la log ou à la fin du serveur, mais le noeud.js juste se bloque tout simplement. Entourer mon code d'un try-catch ne fonctionne pas non plus puisque tout est fait de façon asynchrone. J'aimerais savoir ce que font les autres dans leurs serveurs de production.

129
demandé sur TiansHUo 2011-05-14 06:04:28

8 réponses

D'autres réponses sont vraiment folles comme vous pouvez le lire dans les propres documents de Node à http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception

Si quelqu'un est à l'aide d'autres a déclaré réponses de lecture Nœud Docs:

noter que uncaughtException est un mécanisme très rudimentaire pour la manipulation d'exceptions et peut être retiré dans le futur

donc après être allé je suis finalement arrivé avec ce que le document de Noeud lui-même suggère:

ne l'utilisez pas, utilisez domains avec cluster à la place. Si vous utilisez uncaughtException , redémarrez votre application après chaque exception non bloquée!

Solution DOMAINE avec Cluster

Ce que nous voulons faire est d'envoyer une réponse d'erreur à la requête qui a déclenché l'erreur, tout en laissant les autres finir dans leur temps normal, et arrêter d'écouter de nouvelles requêtes dans ce travailleur.

de cette façon, l'utilisation du domaine va de pair avec le module cluster, puisque le processus maître peut bifurquer un nouveau worker lorsqu'un worker rencontre une erreur. Voir le code ci-dessous pour comprendre ce que je veux dire

en utilisant Domain , et la résilience de séparer notre programme en plusieurs processus de travail en utilisant Cluster , nous pouvons réagir de manière plus appropriée, et traiter les erreurs avec beaucoup plus de sécurité.

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);
} 

bien que Domain soit en attente d'Annulation et sera supprimé comme le nouveau remplacement vient comme indiqué dans la Documentation de Node

ce module est en attente d'annulation. Une fois qu'une API de remplacement a été finalisée, ce module sera complètement déprécié. Les utilisateurs qui doivent absolument avoir la fonctionnalité que les domaines fournir peut compter sur elle pour le moment, mais doit s'attendre à migrer vers une solution différente dans l'avenir.

mais jusqu'à ce que le nouveau remplacement n'est pas introduit, domaine avec Cluster est la seule bonne solution ce que la Documentation de Noeud suggère.

pour une compréhension approfondie Domain et Cluster lire

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

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

merci à @Stanley Luo pour nous avoir partagé cette merveilleuse explication en profondeur sur les clusters et les domaines

Cluster Et Domaines

109
répondu Abdul Jabbar Dumrai 2017-02-08 07:05:03

j'ai placé ce code sous mes déclarations require et global declarations:

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

ça me va. la seule chose que je n'aime pas, c'est que je n'ai pas autant d'infos que si je laissais tomber ce truc.

69
répondu hvgotcodes 2011-05-14 02:08:47

comme mentionné ici vous trouverez error.stack fournit un message d'erreur plus complet tel que le numéro de ligne qui a causé l'erreur:

process.on('uncaughtException', function (error) {
   console.log(error.stack);
});
27
répondu Sean Bannister 2017-05-23 10:31:16

Essayer supervisor

npm install supervisor
supervisor app.js

ou vous pouvez installer forever à la place.

tout ce que cela va faire est de récupérer votre serveur quand il plante en le redémarrant.

forever peut être utilisé dans le code pour récupérer avec élégance tous les processus qui s'écrasent.

les forever docs ont des informations solides sur le traitement des sorties/erreurs par programmation.

11
répondu Raynos 2015-03-30 22:57:02

L'utilisation de try-catch peut résoudre les erreurs uncaught, mais dans certaines situations complexes, il ne fera pas le bon travail comme attraper la fonction async. Rappelez-vous que dans Node, n'importe quel appel de fonction async peut contenir une opération de plantage d'application potentielle.

utiliser uncaughtException est une solution de contournement, mais il est reconnu comme inefficace et est susceptible d'être supprimé dans les futures versions de Noeud, donc ne comptez pas sur elle.

la solution idéale est d'utiliser le domaine: http://nodejs.org/api/domain.html

pour vous assurer que votre application est en marche et fonctionne même si votre serveur est bloqué, utilisez les étapes suivantes:

  1. utiliser un groupe de noeuds pour bifurquer plusieurs processus par cœur. Donc, si un processus est mort, un autre processus automatique de démarrage. Check out: http://nodejs.org/api/cluster.html

  2. utiliser le domaine pour attraper async operation au lieu d'utiliser try-catch ou uncaught. Je ne dis pas que try-catch ou uncaught est une mauvaise idée!

  3. utilisez jamais/superviseur de surveiller vos services

  4. ajouter un démon pour exécuter votre application node: http://upstart.ubuntu.com

espérons que cette aide!

7
répondu Nam Nguyen 2013-09-06 11:48:06

donner un essai à pm2 module noeud il est très cohérent et a une grande documentation. Responsable du processus de Production pour le noeud.applications js avec un équilibreur de charge intégré. veuillez éviter uncaughtException pour ce problème. https://github.com/Unitech/pm2

4
répondu Virendra Rathore 2016-04-08 10:19:04

UncaughtException est "un très un mécanisme grossier" (tellement vrai) et les domaines sont obsolète maintenant. Cependant, nous avons encore besoin d'un mécanisme pour détecter les erreurs autour de (logique) domaines. La bibliothèque:

https://github.com/vacuumlabs/yacol

peut vous aider à le faire. Avec un peu d'écriture supplémentaire, vous pouvez avoir une belle sémantique de domaine tout autour de votre code!

0
répondu Tomas Kulich 2016-11-26 11:26:09

fonctionne très bien sur restify:

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();
});
0
répondu PH Andrade 2017-02-14 03:19:09