如何防止 node.js 崩溃?try-catch 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5999373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I prevent node.js from crashing? try-catch doesn't work
提问by TiansHUo
From my experience, a php server would throw an exception to the log or to the server end, but node.js just simply crashes. Surrounding my code with a try-catch doesn't work either since everything is done asynchronously. I would like to know what does everyone else do in their production servers.
根据我的经验,php 服务器会向日志或服务器端抛出异常,但 node.js 只是崩溃。用 try-catch 包围我的代码也不起作用,因为一切都是异步完成的。我想知道其他人在他们的生产服务器上做什么。
采纳答案by Airy
Other answers are really insane as you can read at Node's own documents at http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception
其他答案真的很疯狂,因为您可以在http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception 上阅读 Node 自己的文档
If someone is using other stated answers read Node Docs:
如果有人使用其他陈述的答案,请阅读 Node Docs:
Note that
uncaughtExceptionis a very crude mechanism for exception handling and may be removed in the future
请注意,这
uncaughtException是一种非常粗糙的异常处理机制,将来可能会被删除
PM2
PM2
First of all, I would highly recommend installing PM2for Node.js. PM2 is really great at handling crash and monitoring Node apps as well as load balancing. PM2 immediately starts the Node app whenever it crashes, stops for any reason or even when server restarts. So, if someday even after managing our code, app crashes, PM2 can restart it immediately. For more info, Installing and Running PM2
首先,我会强烈建议安装PM2的Node.js。PM2 非常擅长处理崩溃和监控 Node 应用程序以及负载平衡。每当 Node 应用程序崩溃、因任何原因停止甚至服务器重新启动时,PM2 都会立即启动它。因此,如果有一天即使在管理我们的代码后,应用程序崩溃,PM2 也可以立即重新启动它。有关更多信息,请安装和运行 PM2
Now coming back to our solution to preventing the app itself from crashing.
现在回到我们防止应用程序本身崩溃的解决方案。
So after going through I finally came up with what Node document itself suggests:
所以在经历了这些之后,我终于想出了 Node 文档本身的建议:
Don't use
uncaughtException, usedomainswithclusterinstead. If you do useuncaughtException, restart your application after every unhandled exception!
不要用
uncaughtException,用domainswithcluster代替。如果您确实使用了uncaughtException,请在每个未处理的异常后重新启动您的应用程序!
DOMAINwith Cluster
带集群的域
What we actually do is send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.
我们实际做的是向触发错误的请求发送错误响应,同时让其他请求在正常时间完成,并停止侦听该工作线程中的新请求。
In this way, domain usage goes hand-in-hand with the cluster module, since the master process can fork a new worker when a worker encounters an error. See the code below to understand what I mean
通过这种方式,域的使用与集群模块密切相关,因为当工作进程遇到错误时,主进程可以派生一个新的工作进程。请参阅下面的代码以了解我的意思
By using Domain, and the resilience of separating our program into multiple worker processes using Cluster, we can react more appropriately, and handle errors with much greater safety.
通过使用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);
}
Though Domainis pending deprecation and will be removed as the new replacement comes as stated in Node's Documentation
虽然Domain正在等待弃用,并将随着新的替代品的出现而被删除,如 Node 的文档中所述
This module is pending deprecation. Once a replacement API has been finalized, this module will be fully deprecated. Users who absolutely must have the functionality that domains provide may rely on it for the time being but should expect to have to migrate to a different solution in the future.
此模块正在等待弃用。替换 API 完成后,该模块将被完全弃用。绝对必须拥有域提供的功能的用户可能暂时依赖它,但预计将来必须迁移到不同的解决方案。
But until the new replacement is not introduced, Domain with Cluster is the only good solution what Node Documentation suggests.
但是在没有引入新的替代品之前,Domain with Cluster 是 Node 文档建议的唯一好的解决方案。
For in-depth understanding Domainand Clusterread
为了深入理解Domain和Cluster阅读
https://nodejs.org/api/domain.html#domain_domain(Stability: 0 - Deprecated)
https://nodejs.org/api/domain.html#domain_domain(Stability: 0 - Deprecated)
https://nodejs.org/api/cluster.html
https://nodejs.org/api/cluster.html
Thanks to @Stanley Luo for sharing us this wonderful in-depth explanation on Cluster and Domains
感谢@Stanley Luo 与我们分享关于集群和域的精彩深入解释
回答by hvgotcodes
I put this code right under my require statements and global declarations:
我把这段代码放在我的 require 语句和全局声明下面:
process.on('uncaughtException', function (err) {
console.error(err);
console.log("Node NOT Exiting...");
});
works for me. the only thing i don't like about it is I don't get as much info as I would if I just let the thing crash.
对我来说有效。我唯一不喜欢它的一点是,如果我让这件事崩溃,我不会得到尽可能多的信息。
回答by Sean Bannister
回答by Raynos
Try supervisor
尝试 supervisor
npm install supervisor
supervisor app.js
Or you can install foreverinstead.
或者你可以安装forever。
All this will do is recover your server when it crashes by restarting it.
所有这些都可以在服务器崩溃时通过重新启动来恢复它。
forevercan be used within the code to gracefully recover any processes that crash.
forever可以在代码中使用以优雅地恢复任何崩溃的进程。
The foreverdocs have solid information on exit/error handling programmatically.
该forever文件对出口/错误处理程序可靠的信息。
回答by Nam Nguyen
Using try-catch may solve the uncaught errors, but in some complex situations, it won't do the job right such as catching async function. Remember that in Node, any async function calls can contain a potential app crashing operation.
使用 try-catch 可以解决未捕获的错误,但在一些复杂的情况下,它不会正确地完成工作,例如捕获异步函数。请记住,在 Node 中,任何异步函数调用都可能包含潜在的应用程序崩溃操作。
Using uncaughtExceptionis a workaround but it is recognized as inefficient and is likely to be removed in the future versions of Node, so don't count on it.
使用uncaughtException是一种解决方法,但它被认为是低效的,并且可能会在 Node 的未来版本中被删除,所以不要指望它。
Ideal solution is to use domain: http://nodejs.org/api/domain.html
理想的解决方案是使用域:http: //nodejs.org/api/domain.html
To make sure your app is up and running even your server crashed, use the following steps:
要确保即使服务器崩溃,您的应用程序也能正常运行,请使用以下步骤:
use node cluster to fork multiple process per core. So if one process died, another process will be auto boot up. Check out: http://nodejs.org/api/cluster.html
use domain to catch async operation instead of using try-catch or uncaught. I'm not saying that try-catch or uncaught is bad thought!
use forever/supervisor to monitor your services
add daemon to run your node app: http://upstart.ubuntu.com
使用节点集群为每个核心分叉多个进程。因此,如果一个进程死亡,另一个进程将自动启动。查看:http: //nodejs.org/api/cluster.html
使用域来捕获异步操作,而不是使用 try-catch 或未捕获。我并不是说尝试捕获或未捕获是不好的想法!
使用永远/主管来监控您的服务
添加守护进程以运行您的节点应用程序:http: //upstart.ubuntu.com
hope this helps!
希望这可以帮助!
回答by Virendra Rathore
Give a try to pm2 node module it is far consistent and has great documentation. Production process manager for Node.js apps with a built-in load balancer. please avoid uncaughtException for this problem. https://github.com/Unitech/pm2
尝试使用 pm2 节点模块,它非常一致并且有很好的文档。具有内置负载均衡器的 Node.js 应用程序的生产流程管理器。请避免出现此问题的 uncaughtException。 https://github.com/Unitech/pm2
回答by Tomas Kulich
UncaughtException is "a very crude mechanism" (so true) and domains are deprecated now. However, we still need some mechanism to catch errors around (logical) domains. The library:
UncaughtException 是“一种非常粗糙的机制”(如此真实),现在不推荐使用域。但是,我们仍然需要某种机制来捕获(逻辑)域周围的错误。图书馆:
https://github.com/vacuumlabs/yacol
https://github.com/vacuumlabs/yacol
can help you do this. With a little of extra writing you can have nice domain semantics all around your code!
可以帮助你做到这一点。通过一些额外的编写,您可以在代码周围拥有良好的域语义!
回答by PH Andrade
Works great on restify:
在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();
});

