如何防止 Node.js 崩溃? try-catch 不起作用
根据我的经验,php 服务器会向日志或服务器端抛出异常,但 Node.js 只是崩溃。用 try-catch 包围我的代码也不起作用,因为一切都是异步完成的。我想知道其他人在他们的生产服务器中做了什么。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
PM2
首先,我强烈建议为
Node.js
安装PM2
。 PM2 非常擅长处理崩溃、监控 Node 应用程序以及负载平衡。每当 PM2 崩溃、因任何原因停止甚至服务器重新启动时,PM2 都会立即启动 Node 应用程序。因此,如果有一天,即使在管理我们的代码之后,应用程序崩溃了,PM2 也可以立即重新启动它。有关更多信息,安装和运行 PM2其他答案真的很疯狂,您可以阅读 Node 自己的文档在 http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception
如果有人使用其他规定的答案,请阅读节点文档:
现在回到我们的解决方案,以防止应用程序本身崩溃。
因此,在浏览完之后,我终于得出了 Node 文档本身的建议:
DOMAIN 和 Cluster
我们实际做的是向触发错误的请求发送错误响应,同时让其他请求在正常时间内完成,并停止侦听新请求在那名工人身上。
通过这种方式,域的使用与集群模块密切相关,因为当工作进程遇到错误时,主进程可以派生一个新的工作进程。请参阅下面的代码以了解我的意思
通过使用
Domain
,以及使用Cluster
将我们的程序分离为多个工作进程的弹性,我们可以做出更适当的反应,并处理错误具有更高的安全性。尽管
Domain
正在等待弃用,并将随着新的替代品的出现而被删除,如 Node 文档中所述但在没有引入新的替代方案之前,带有集群的域是节点文档建议的唯一好的解决方案。
要深入了解
Domain
和Cluster
,请阅读https://nodejs.org/api/domain.html#domain_domain(稳定性:0 - 已弃用
)https://nodejs.org/api/cluster.html
感谢@Stanley Luo 与我们分享关于集群和域的精彩深入解释
集群和集群域名
PM2
First of all, I would highly recommend installing
PM2
forNode.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 PM2Other 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
If someone is using other stated answers read Node Docs:
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:
DOMAIN with 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 usingCluster
, we can react more appropriately, and handle errors with much greater safety.Though
Domain
is pending deprecation and will be removed as the new replacement comes as stated in Node's DocumentationBut until the new replacement is not introduced, Domain with Cluster is the only good solution what Node Documentation suggests.
For in-depth understanding
Domain
andCluster
readhttps://nodejs.org/api/domain.html#domain_domain(Stability: 0 - Deprecated
)https://nodejs.org/api/cluster.html
Thanks to @Stanley Luo for sharing us this wonderful in-depth explanation on Cluster and Domains
Cluster & Domains
我将此代码放在我的 require 语句和全局声明下:
对我有用。我唯一不喜欢它的是,如果我让它崩溃的话,我不会得到尽可能多的信息。
I put this code right under my require statements and global declarations:
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.
正如此处所述,您'会发现
error.stack
提供了更完整的错误消息,例如导致错误的行号:As mentioned here you'll find
error.stack
provides a more complete error message such as the line number that caused the error:尝试
supervisor
或者你可以安装
永远
代替。所有这一切都会在服务器崩溃时通过重新启动来恢复它。
可以在代码中使用
forever
来正常恢复任何崩溃的进程。forever
文档提供了有关以编程方式处理退出/错误的可靠信息。Try
supervisor
Or you can install
forever
instead.All this will do is recover your server when it crashes by restarting it.
forever
can be used within the code to gracefully recover any processes that crash.The
forever
docs have solid information on exit/error handling programmatically.使用 try-catch 可以解决未捕获的错误,但在某些复杂的情况下,它无法正确完成工作,例如捕获异步函数。请记住,在 Node 中,任何异步函数调用都可能包含潜在的应用程序崩溃操作。
使用 uncaughtException 是一种解决方法,但它被认为效率低下,并且可能会在 Node 的未来版本中被删除,因此不要指望它。
理想的解决方案是使用域:http://nodejs.org/api/domain.html
即使服务器崩溃,也要确保您的应用程序正常运行,请使用以下步骤:
使用节点集群为每个核心分叉多个进程。因此,如果一个进程死亡,另一个进程将自动启动。查看:http://nodejs.org/api/cluster.html
使用域捕获异步操作而不是使用 try-catch 或 uncaught。我并不是说 try-catch 或 uncaught 是个坏主意!
使用forever/supervisor来监控你的服务
添加守护进程来运行你的节点应用程序:http://upstart.ubuntu.com
希望这有帮助!
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.
Using
uncaughtException
is 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.Ideal solution is to use domain: 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
hope this helps!
尝试一下 pm2 节点模块,它非常一致并且有很棒的文档。具有内置负载均衡器的 Node.js 应用程序的生产流程管理器。请避免出现此问题的 uncaughtException。
https://github.com/Unitech/pm2
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
在 Restify 上效果很好:
Works great on restify:
默认情况下,Node.js 通过将堆栈跟踪打印到 stderr 并以代码 1 退出(覆盖任何先前设置的 process.exitCode)来处理此类异常。
了解更多
By default, Node.js handles such exceptions by printing the stack trace to stderr and exiting with code 1, overriding any previously set process.exitCode.
know more
UncaughtException 是“一种非常粗糙的机制”(确实如此),并且域现在已被弃用。然而,我们仍然需要某种机制来捕获(逻辑)域周围的错误。库:
https://github.com/vacuumlabs/yacol
可以帮助您做到这一点。通过一些额外的编写,您可以在代码中拥有良好的域语义!
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:
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!
为了避免 NodeJS 服务器因 unhandledRejection 或 uncaughtException 崩溃,请将以下代码片段放入您的入口文件 main.ts 中
To avoid nodejs server crashing because of unhandledRejection or uncaughtException, let put the below snippet into your entry file main.ts