NodeJS异常处理uncaughtException篇
很多 NodeJS 的开发者在抱怨异常处理太麻烦,我们会通过一些列博客梳理一下NodeJS中常见的异常处理的手段。
和大多数编程语言一样,在 NodeJS 里可以通过throw抛出一个异常:
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是脆弱的这个认识,需要开发者加深对这门语言异常处理机制的了解。
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 就可以阻止服务器的进程退出呢? 答案是可以,但是不要这么做!。看这个例子:
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 来模拟请求
ab -n 1000 -c 20 http://localhost:8018/weather
糟糕!请求一直在等待,内存上涨。原因在于res.end 永远不会执行,现有的I/O处于等待的状态,已经开辟的资源不仅不会被释放,而且服务器还在不知疲倦地接受新的用户请求。
在 NodeJS 中处理异常是代价高昂的,而且一不小心就会导致内存泄露和让应用程序处于不稳定的状态。为了提高健壮性,我们可以用Cluster模式,由之而来的推荐做法是: - 针对发生异常的请求返回一个错误代码 - 出错的Worker不再接受新的请求 - 退出关闭Worker进程
本文系OneAPM工程师编译整理。OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客。
NodeJS异常处理uncaughtException篇的更多相关文章
- nodejs学习--express篇
express篇:http://www.runoob.com/nodejs/nodejs-express-framework.html Express 提供了内置的中间件 express.static ...
- .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
dump文件相信有些朋友已经很熟悉了,dump文件的作用在于保存进程运行时的堆栈信息,方便日后排查软件故障,提升软件质量.关于dump分析工具windbg.adplus的文章更多了,如果您还不知道怎么 ...
- nodejs异常处理过程/获取nodejs异常类型/写一个eggjs异常处理中间件
前言 今天想写一下eggjs的自定义异常处理中间件,在写的时候遇到了问题,这个错误我捕获不到类型?? 处理过程,不喜欢看过程的朋友请直接看解决方法和总结 看一下是什么: 抛出的异常是检验失败异常Val ...
- Nodejs系列-01-开篇
1.解决什么问题 1. 并发连接 举个例子,想象一个场景,我们在银行排队办理业务,我们看看下面两个模型. (1)系统线程模型: 这种模型的问题显而易见,服务端只有一个线程,并发请求(用户)到达只能处理 ...
- nodejs初学————安装篇(iis8.5+windows8.1)
nodejs很久前就想玩玩,不过一直没时间,昨晚花了4个小时来捣鼓到iis上架设成功了,废话不说了. PS:我的系统是windows8.1 x64,所以自带iis8.5的,下载的文件也是x64的. N ...
- Python_day8_面向对象(多态、成员修饰符、类中特殊方法、对象边缘知识)、异常处理之篇
一.面向对象之多态 1.多态:简而言子就是多种形态或多种类型 python中不支持多态也用不到多态,多态的概念是应用与java/C#中指定传参的数据类型, java多态传参:必须是传参数的数据类型或传 ...
- 边走边学Nodejs (基础入门篇)
1.什么是Node.js Nodejs ,或者node, 是一个基于ChromeJavaScript执行时建立的平台.用于方便地搭建响应速度快.易于扩展的网络应用.Node.js 使用事件驱动, 非堵 ...
- 开心菜鸟系列学习笔记--------初探Nodejs(了解篇)
一Node.js开始学习了! 1) 输出hellow worlds a.建一个js文件 hello.js 写 console.info('hellow world !!!'); 进入终 ...
- 搭建前端监控系统(三)NodeJs服务器部署篇
===================================================================== 监控系统预览地址: DEMO地址 GIT代码仓库地址 ...
随机推荐
- 从0 开始 WPF MVVM 企业级框架实现与说明 ---- 第三讲 WPF中 DataTemplate
后面在我们这项目中会大量用到模板,主要指的是空间模板,数据模板会用得比较少,下面我想介绍下控件模板和数据模板,我看到有位大神写得比较不错,我整理了下,让大家能更好理解,供大家参考, 首先介绍 Data ...
- ref和out的区别
ref类型参数是按地址传递,能改变原来的数值.使用ref传参前,变量必须赋值. 带有ref类型参数的函数,不会清空变量,所以离开该函数的时候,所有ref引用的变量可以赋值也可以不赋值. out类型参数 ...
- AppCan移动平台开发常见问题解答
在使用AppCan移动平台开发跨平台APP时,有开发者会遇到一些问题, 不急,跟笔者一起来聊一聊使用AppCan平台开发中常见问题的解答方法. 问1.正常是按照官网提供的4个iphone启动图尺寸来做 ...
- JavaScript高级程序设计之JSON
IE8以下请求助神之Douglas Crockford:https://github.com/douglascrockford/json-js JSON是一种格式化的字符串,特别适合在网络上传输,由D ...
- ASP运行流程(主要的类笔记)
个人笔记:参考汤姆大叔的MVC之前那些事系列整理 client端发送页面请求,被IIS的某个进程截获,它根据申请的页面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll ...
- Mono for Android (3)-- AbsoluteLayout、FrameLayout、LinearLayout、RelativeLayout、TableLayout
AbsoluteLayout:允许开发人员将视图放在所定义的位置.该布局已经过时了,建议改用其他 FrameLayout:最简单的布局选项,其设计目的是在屏幕上显示单个对象.所有元素都固定在左上角.如 ...
- python并行迭代
并行迭代:同时并行遍历两个列表 for line1,line2 in zip(line1_list, line2_list): ... 无聊,贴一段刚才的代码: import sys import s ...
- 移植net-snmp到开发板(mini210)
1.安装交叉编译工具arm-linux-gcc 2.下载net-snmp源码安装包 3.解压安装包 4../configure --build=i686-linux --host=arm-linux ...
- 巧用 .NET 中的「合并运算符」获得 URL 中的参数
获取 URL 中的 GET 参数,无论用什么语言开发网站,几乎是必须会用到的代码.但获取 URL 参数经常需要注意一点就是要先判断是否有这个参数存在,如果存在则取出,如果不存在则用另一个值.这个运算称 ...
- Git学习小结(第三次作业)
本文主要总结一下在学习和使用git中一些用到的命令. 参考教程:廖雪峰git教程 在windows上安装git 下载使用环境:http://msysgit.github.io/, 安装一路默认即可. ...