一尘不染

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

node.js

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


阅读 272

收藏
2020-07-07

共1个答案

一尘不染

您可以从Node自己的文档中(http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception)阅读其他答案,真是太疯狂了

如果有人在使用其他规定的答案,请阅读Node Docs:

请注意,这uncaughtException是异常处理的非常粗糙的机制,以后可能会删除

下午2

首先,我会强烈建议安装PM2Node.js。PM2非常适合处理崩溃和监视Node应用程序以及负载平衡。每当PM2崩溃时,PM2都会立即启动Node应用程序,无论出于任何原因甚至在服务器重新启动时都会停止。因此,即使有一天即使在管理完我们的代码之后,应用程序崩溃,PM2仍可以立即重新启动它。有关更多信息,请安装并运行PM2

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

因此,经过研究之后,我终于想到了Node文档本身的建议:

不要使用uncaughtException,而是使用domainswith
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正在等待弃用,但随着新的替换如Node文档中所述,将被删除

该模块即将弃用。替代API最终确定后,该模块将被完全弃用。绝对必须具有域提供的功能的用户暂时可能会依赖它,但是应该期望将来必须迁移到其他解决方案。

但是直到没有引入新的替代方案之前,“带群集的域”是Node Documentation建议的唯一好的解决方案。

供深入了解DomainCluster阅读

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

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

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

集群与域

2020-07-07