未处理的拒绝后我需要重新启动我的应用程序吗

问题描述 投票:0回答:1

我有一个 NodeJS 应用程序(服务器)并使用一些第 3 方 npm 模块。 另外在我的应用程序中,我有以下代码:

process.on("unhandledRejection", (reason, promise) => {
    console.error(`Unhandled Rejection at: ${promise} reason: ${reason}`);
    restartApp(); // ← Is this a must action?
});

似乎并不是所有的承诺都被正确拒绝,在第 3 方模块中,也许也在我的代码中。 我知道这是使用此事件处理程序的最后一个资源。

捕获此未处理拒绝事件后的问题,我需要重新启动我的应用程序吗?

javascript node.js es6-promise
1个回答
9
投票

将错误分为两大类很有用:操作错误和程序员错误。

操作错误是正确编写的程序遇到的(不可避免的)运行时问题,例如磁盘已满、网络连接丢失等。

程序员错误是由代码中的错误或疏忽引起的,无法处理,因为它们会导致程序进入未知状态,它们可能在您的代码中您正在调用的模块中。

应对程序员错误的最佳做法是立即崩溃。您应该使用重新启动程序(见下文)来运行程序,该重新启动程序将在发生崩溃时自动重新启动程序。有了重新启动器,崩溃是在遇到暂时的程序员错误时恢复可靠服务的最快方法。

如果错误是操作错误,则尝试恢复或重试操作可能是有意义的(如果有意义的话)。例如,如果您收到 400 个错误,则重试 REST 请求是没有意义的,但如果您收到 500 个错误(系统可能会恢复),则可能会出现这种情况。 在这个非常有用的指南中查看更多内容:

https://www.joyent.com/node-js/product/design/errors

在您的具体情况下,您正在处理 unhandledRejection,这意味着应用程序处于未定义状态...与 unhandledException 非常相似,最好的办法是清理需要完成的任何内容,然后退出或重新启动,同时记录错误(这非常重要!错误是每天、每小时还是每分钟发生?)

我建议使用过程监视器,例如

PM2

Forever。当您因错误退出时,它们可以自动重新启动,并执行许多其他很酷的操作,例如记录这些事件。 这是 Heroku 关于同一主题的另一篇精彩指南:

https://blog.heroku.com/best-practices-nodejs-errors

博主(Julián Duque)甚至总结了一些处理这些事件的最佳实践:

https://blog.heroku.com/best-practices-nodejs-errors#putting-it-all-together

这看起来有点像这样:

const http = require('http') const terminate = require('./terminate') const server = http.createServer(...) const exitHandler = terminate(server, { coredump: false, timeout: 500 }) process.on('uncaughtException', exitHandler(1, 'Unexpected Error')) process.on('unhandledRejection', exitHandler(1, 'Unhandled Promise')) process.on('SIGTERM', exitHandler(0, 'SIGTERM')) process.on('SIGINT', exitHandler(0, 'SIGINT'))

终止模块:

function terminate (server, options = { coredump: false, timeout: 500 }) { return (code, reason) => (err, promise) => { // Exit function const exit = () => { options.coredump ? process.abort() : process.exit(code) } if (err && err instanceof Error) { // Log error information, use a proper logging library here :) console.log(err.message, err.stack) } // Attempt a graceful shutdown server.close(exit) setTimeout(exit, options.timeout).unref() } } module.exports = terminate

我认为这种对这些事件进行托管、集中处理的方式是正确的方法。

© www.soinside.com 2019 - 2024. All rights reserved.