小编典典

如何防止 node.js 崩溃?尝试捕捉不起作用

all

根据我的经验,php 服务器会向日志或服务器端抛出异常,但 node.js 只是简单地崩溃。用 try-catch
包围我的代码也不起作用,因为一切都是异步完成的。我想知道其他人在他们的生产服务器上做什么。


阅读 75

收藏
2022-08-08

共1个答案

小编典典

PM2

首先,我强烈建议安装PM2. Node.jsPM2 非常擅长处理崩溃和监控 Node
应用程序以及负载平衡。每当它崩溃、因任何原因停止甚至服务器重新启动时,PM2 都会立即启动 Node
应用程序。因此,如果有一天即使在管理我们的代码之后,应用程序崩溃了,PM2 也可以立即重新启动它。更多信息,安装和运行
PM2

其他答案真的很疯狂,因为您可以在http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception上阅读
Node
自己的文档

如果有人使用其他声明的答案,请阅读 Node Docs:

请注意,这uncaughtException是一种非常粗糙的异常处理机制,将来可能会被删除

现在回到我们防止应用程序本身崩溃的解决方案。

因此,在经历了之后,我终于想出了 Node 文档本身的建议:

不要用uncaughtException,用domainswithcluster代替。如果您确实使用uncaughtException,请在每个未处理的异常后重新启动您的应用程序!

*带 *集群的 域* *

我们实际上要做的是向触发错误的请求发送错误响应,同时让其他人在正常时间完成,并停止在该工作人员中侦听新请求。

通过这种方式,域使用与集群模块密切相关,因为当一个工作人员遇到错误时,主进程可以派生一个新的工作人员。请参阅下面的代码以了解我的意思

通过使用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正在等待弃用,并且将被删除,因为新的替代品如 Node 的文档中所述

此模块正在等待弃用。一旦替代 API 完成,该模块将被完全弃用。绝对必须拥有域提供的功能的用户可能暂时依赖它,但预计将来必须迁移到不同的解决方案。

但是在没有引入新的替代品之前,Domain with Cluster 是 Node Documentation 建议的唯一好的解决方案。

为了深入理解DomainCluster阅读

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

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

感谢@Stanley Luo 为我们分享了关于集群和域的精彩深入解释

集群和域

2022-08-08