NodeJS异常处理uncaughtException篇

NodeJS异常处理uncaughtException篇

王龑 — APRIL 08, 2015express

不少 NodeJS 的开发者在抱怨异常处理太麻烦,咱们会经过一些列博客梳理一下NodeJS中常见的异常处理的手段。
和大多数编程语言同样,在 NodeJS 里能够经过throw抛出一个异常:apache

throw new Error('Catch me');

为了捕获这个异常须要把代码包在Try Catch中:编程

try{
    throw new Error('Catch me');
}catch(e){
    // error captured
}

然而,因为 NodeJS 的异步特性,上述代码只需稍加改造就会失效:服务器

try{
    process.nextTick(function my_app(){
        throw new Error('Catch me');
    })
}catch(e){
    // never called
}

在现实世界里,异常老是会产生在某个模块中。所谓模块就是能完成一个功能的单元,即便是一个简单的函数也能够被看作一个模块。随着项目代码行数增多,异步嵌套的复杂性增强,常常会有异常没捕获的状况发生。一个没有很强健壮性的 NodeJS 应用,会由于一个未捕获的异常就整个挂掉,致使服务不可用。要改变你们以为NodeJS是脆弱的这个认识,须要开发者加深对这门语言异常处理机制的了解。app

uncaughtException

uncaughtException 实际上是 NodeJS 进程的一个事件。若是进程里产生了一个异常而没有被任何Try Catch捕获会触发这个事件。为了简化问题,咱们仍是先看看同步状况下的例子。异步

function external() {
    throw new Error('Catch me');
}

function internal() {
    external();
}

internal(); //error will be thrown

在命令行里执行这个程序,脚本会在抛出异常的那一行中断。接下来,因为没有Try Catch,异常会一直冒泡直到事件循环为止,而NodeJS对异常的默认处理很是简单,处理的代码 相似 于:编程语言

function _MyFatalException(err){
    if(!process.emit('uncaughtException',err)){
        console.error(err.stack);
        process.emit('exit',1);
    }
}

NodeJS对于未捕获异常的默认处理是: - 触发 uncaughtException 事件 - 若是 uncaughtException 没有被监听,那么 - 打印异常的堆栈信息 - 触发进程的 exit 事件函数

若是你正在用 NodeJS 开发服务器,那么你确定不但愿偶然的一个异常让整个服务器挂掉。那么是否是只要监听了 uncaughtException 就能够阻止服务器的进程退出呢? 答案是能够,可是不要这么作!。看这个例子:oop

var express = require('express');

function external(cb) {
    process.nextTick(function () {
        throw new Error();
        cb.call(null, 'sunny');
    })
}

var app = express();
app.get('/weather', function (req, res) {
    external(function (data) {
        res.end('Weather of Beijing is ' + data);
    })
})
app.listen(8018);


function noop(){}
process.on('uncaughtException', noop)

上面这个例子假设用户访问站点的时候能够看到当地的天气,咱们用 apache2-utils 来模拟请求ui

ab -n 1000 -c 20 http://localhost:8018/weather

糟糕!请求一直在等待,内存上涨。缘由在于res.end 永远不会执行,现有的I/O处于等待的状态,已经开辟的资源不只不会被释放,并且服务器还在不知疲倦地接受新的用户请求。

在 NodeJS 中处理异常是代价高昂的,并且一不当心就会致使内存泄露和让应用程序处于不稳定的状态。为了提升健壮性,咱们能够用Cluster模式,由之而来的推荐作法是: - 针对发生异常的请求返回一个错误代码 - 出错的Worker再也不接受新的请求 - 退出关闭Worker进程


本文做者系OneAPM工程师王龑 ,想阅读更多好的技术文章,请访问OneAPM官方技术博客。

相关文章
相关标签/搜索