it-swarm.com.de

Wie verhindere ich, dass node.js abstürzt? Try-Catch funktioniert nicht

Aus meiner Erfahrung würde ein PHP-Server eine Ausnahme für das Protokoll oder das Server-Ende auslösen, aber node.js stürzt einfach ab. Das Umgeben meines Codes mit einem Try-Catch funktioniert auch nicht, da alles asynchron ausgeführt wird. Ich würde gerne wissen, was alle anderen auf ihren Produktionsservern tun.

134
TiansHUo

Andere Antworten sind wirklich verrückt, wie Sie in den eigenen Dokumenten von Node unter http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception nachlesen können.

Wenn jemand andere festgelegte Antworten verwendet, lesen Sie Node Docs:

Beachten Sie, dass uncaughtException ein sehr grobmechanischer Mechanismus für die Ausnahmebehandlung ist und in der Zukunft entfernt werden kann

PM2

Zunächst würde ich wärmstens empfehlen, PM2 für Node.js zu installieren. PM2 eignet sich hervorragend für den Umgang mit Abstürzen und das Überwachen von Knoten-Apps sowie für den Lastausgleich. PM2 startet die Node-App sofort, wenn sie abstürzt, aus irgendeinem Grund gestoppt wird oder der Server neu gestartet wird. Wenn also die App nach dem Verwalten des Codes eines Tages abstürzt, kann PM2 ihn sofort neu starten. Weitere Informationen finden Sie unter PM2 installieren und ausführen

Kehren Sie jetzt zu unserer Lösung zurück, um den Absturz der App selbst zu verhindern.

Nachdem ich durchgegangen war, kam ich schließlich zu dem, was das Knotendokument selbst vorschlägt:

Verwenden Sie nicht uncaughtException, sondern stattdessen domains mit cluster. Wenn Sie uncaughtException verwenden, starten Sie Ihre Anwendung nach jeder nicht behandelten Ausnahme erneut!

DOMAIN mit Cluster

Was wir tatsächlich tun, ist eine Fehlerantwort auf die Anforderung, die den Fehler ausgelöst hat, zu senden, während die anderen in ihrer normalen Zeit fertiggestellt werden und auf neue Anforderungen in diesem Worker warten.

Auf diese Weise geht die Domänennutzung mit dem Cluster-Modul einher, da der Master-Prozess einen neuen Worker verzweigen kann, wenn ein Worker auf einen Fehler stößt. Sehen Sie den Code unten, um zu verstehen, was ich meine

Durch die Verwendung von Domain und die Widerstandsfähigkeit der Trennung unseres Programms in mehrere Arbeitsprozesse mit Cluster können wir angemessener reagieren und Fehler viel sicherer behandeln.

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

Die Variable Domain steht zwar aus, wird jedoch entfernt, da der neue Ersatz wie in der Dokumentation des Knotens angegeben ist

Dieses Modul steht noch aus. Sobald eine Ersatz-API abgeschlossen ist, wird dieses Modul vollständig abgelehnt. Benutzer, die unbedingt über die Funktionalität von Domains verfügen müssen, können sich vorerst darauf verlassen, sollten aber in der Zukunft auf eine andere Lösung umsteigen müssen.

Die Domäne mit Cluster ist jedoch die einzige gute Lösung, die die Knotendokumentation vorschlägt, bis der neue Ersatz nicht eingeführt wird.

Für ein tieferes Verständnis lesen Sie Domain und Cluster

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

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

Vielen Dank an @Stanley Luo, der uns diese wunderbare ausführliche Erklärung zu Cluster und Domains zur Verfügung gestellt hat

Cluster & Domains

116

Ich habe diesen Code direkt unter meine Anforderung und globalen Deklarationen gestellt:

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

funktioniert bei mir. Das Einzige, was mir nicht gefällt, ist, dass ich nicht so viele Informationen bekomme, wie ich es tun würde, wenn ich die Sache einfach abstürzen lassen würde.

70
hvgotcodes

Wie bereits erwähnt - hier finden Sie, dass error.stack eine vollständigere Fehlermeldung anzeigt, z.

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

Versuchen Sie supervisor

npm install supervisor
supervisor app.js

Oder Sie können stattdessen forever installieren.

Sie müssen lediglich Ihren Server wiederherstellen, wenn er durch Neustart abstürzt.

forever kann im Code verwendet werden, um Prozesse, die abstürzen, ordnungsgemäß wiederherzustellen.

Die forever-Dokumente enthalten programmierte Informationen zur Exit-/Fehlerbehandlung.

12
Raynos

Die Verwendung von try-catch kann die nicht erfassten Fehler beheben, aber in einigen komplexen Situationen wird der Job nicht richtig ausgeführt, z. B. das Abfangen einer asynchronen Funktion. Denken Sie daran, dass in Node alle asynchronen Funktionsaufrufe einen möglichen Absturz der App enthalten können. 

Die Verwendung von uncaughtException ist eine Problemumgehung, die jedoch als ineffizient erkannt wird und in zukünftigen Versionen von Node wahrscheinlich entfernt wird. Zählen Sie also nicht darauf.

Die ideale Lösung ist die Verwendung der Domäne: http://nodejs.org/api/domain.html

Führen Sie die folgenden Schritte aus, um sicherzustellen, dass Ihre App läuft, selbst wenn Ihr Server abgestürzt ist:

  1. verwenden Sie Knotencluster, um mehrere Prozesse pro Kern zu verzweigen. Wenn also ein Prozess gestorben ist, wird ein anderer Prozess automatisch gestartet. Check out: http://nodejs.org/api/cluster.html

  2. verwenden Sie die Domäne, um einen asynchronen Vorgang abzufangen, anstelle von try-catch oder nicht erfasst. Ich sage nicht, dass Try-Catch oder Uncatched ein schlechter Gedanke ist!

  3. verwenden Sie für immer/Supervisor, um Ihre Dienste zu überwachen

  4. fügen Sie einen Dämon hinzu, um Ihre Knoten-App auszuführen: http://upstart.ubuntu.com

hoffe das hilft!

7
Nam Nguyen

Probieren Sie das pm2-Knotenmodul aus, es ist weitestgehend konsistent und hat eine großartige Dokumentation. Produktionsprozessmanager für Node.js-Apps mit integriertem Load Balancer. Bitte vermeiden Sie UncaughtException für dieses Problem. https://github.com/Unitech/pm2

4

Funktioniert gut bei 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
PH Andrade

UncaughtException ist "ein sehr grobmechanischer Mechanismus" (also wahr) und Domains sind jetzt veraltet. Wir brauchen jedoch immer noch einen Mechanismus, um Fehler in (logischen) Domänen aufzufangen. Die Bibliothek:

https://github.com/vacuumlabs/yacol

kann dir dabei helfen. Mit ein wenig extra Schreibweise können Sie Nice-Domain-Semantik rund um Ihren Code verwenden!

0
Tomas Kulich