如何防止 node.js 崩溃? try-catch 不起作用

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

129649 次浏览

试试 supervisor

npm install supervisor
supervisor app.js

或者您可以改为安装 forever

这样做的全部作用就是在服务器崩溃时通过重新启动来恢复它。

可以在代码中使用 forever优雅地恢复任何崩溃的进程。

forever文档有关于程序化退出/错误处理的可靠信息。

我把这段代码放在了我的 request 语句和全局声明下面:

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

我没问题。我唯一不喜欢的就是,如果我让这东西崩溃了,我就得不到那么多信息了。

正如前面提到的 给你,你会发现 error.stack提供了一个更完整的错误消息,比如导致错误的行号:

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

使用 try-catch 可以解决未捕获的错误,但是在一些复杂的情况下,它不能正确地完成捕获异步函数等任务。请记住,在 Node 中,任何异步函数调用都可能包含一个潜在的应用程序崩溃操作。

使用 uncaughtException是一种变通方法,但它被认为效率低下,并且可能在 Node 的未来版本中被删除,因此不要指望它。

理想的解决方案是使用域: http://nodejs.org/api/domain.html

要确保你的应用程序正常运行,甚至你的服务器崩溃了,使用以下步骤:

  1. 使用节点集群为每个核分叉多个进程。因此,如果一个进程死亡,另一个进程将自动启动。看看 http://nodejs.org/api/cluster.html

  2. 使用域捕获异步操作,而不是使用 try-catch 或 uncatch。我并不是说尝试接住或者没接住都是不好的想法!

  3. 使用永久/主管监察你的服务

  4. 添加守护进程来运行节点应用程序: http://upstart.ubuntu.com

希望这个能帮上忙!

PM2

首先,我强烈建议为 Node.js安装 PM2。PM2在处理崩溃、监视 Node 应用程序以及负载平衡方面真的很棒。当 Node 应用程序崩溃、由于任何原因停止甚至服务器重新启动时,PM2都会立即启动它。因此,如果有一天甚至在管理我们的代码之后,应用程序崩溃,PM2可以立即重新启动它。了解更多信息,请登录 安装和运行 PM2

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

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

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

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

因此,在浏览了一遍之后,我终于想出了 Node 文档本身所暗示的内容:

不要使用 uncaughtException,而是使用 domainscluster。如果您确实使用 uncaughtException,在每次未处理的异常后重新启动您的应用程序!

DOMAIN 和 < strong > 簇

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

通过这种方式,域的使用与集群模块密切相关,因为当工作者遇到错误时,主进程可以为新工作者提供分支。请参阅下面的代码以理解我的意思

通过使用 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,这个模块将被完全废弃。绝对必须拥有域提供的功能的用户可能暂时依赖于它,但应该期望将来不得不迁移到不同的解决方案。

但是,在没有引入新的替代方案之前,带集群的域是节点文档建议的唯一好的解决方案。

为了深入了解 DomainCluster阅读

Https://nodejs.org/api/domain.html#domain_domain

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

感谢@Stanley Lo 给我们分享了这篇关于集群和领域的精彩深入解释

群组及范畴

尝试使用 pm2节点模块,它具有很好的一致性和文档说明。带有内置负载平衡器的 Node.js 应用程序生产过程管理器。请避免这个问题的异常。 Https://github.com/unitech/pm2

UncahtException 是“一种非常粗糙的机制”(非常正确) ,现在已经不推荐使用域。但是,我们仍然需要一些机制来捕获(逻辑)域周围的错误。图书馆:

Https://github.com/vacuumlabs/yacol

可以帮助你做到这一点。通过一些额外的编写,您可以在代码周围拥有很好的域语义!

适用于补偿:

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

默认情况下,Node.js 通过将堆栈跟踪打印到 stderr 并使用代码1退出,从而覆盖以前设置的 process.exitCode 来处理这些异常。

了解更多

process.on('uncaughtException', (err, origin) => {
console.log(err);
});