zoukankan      html  css  js  c++  java
  • 避免uncaughtException错误引起node.js进程崩溃

    uncaughtException 未捕获的异常, 当node.js 遇到这个错误,整个进程直接崩溃.

    什么是uncaughtException

    uncaughtException 是一种未捕获的异常,它是node.js 进程上的一个事件,直接挂在 process 上.

    什么时候会遇到uncaughtException

    1.当你的程序出错了

    2.这个错误还没有被 try ... catch 住

    以上2个条件同时发生时, 说明当前的一个异常会一直冒泡到事件循环为止.

    然后打印出异常堆载错误

    接着触发进程 exit 事件,

    最后node.js 进程就会束手就擒的挂掉

    uncaughtException的时候我们能不能挽救一下?

    其实这个时候已经迟了!

    因为上面已经说了 uncaughtException 是挂在 process 上的一个事件

    如果走到这一步,说明异常已经冒泡到事件轮询为止.

    node.js 的特征是什么? 就是异步io,事件轮询,处理回调 --- 轮询已经停止,积压的callbac如何回调,骚年,只好一个人面对 process 的 crash 了!

    一旦走到这步,代码类似这样:

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

    有人说 uncaughtException 事件回调里就什么都不能做吗?

    能做!

    但是很有限.

    当用户访问你的站点时,一个未捕捉的异常触发了 uncaughtException 事件,眼看站点要崩溃,但是傻傻的用户还在浏览器面前痴痴的等待这结果,其实这时你最想告诉用户" 服务器正在维护中,请稍后访问 " 逼格一下提升式了很多,有木有,而且一定会为自己如此棒的用户体验心里暗爽.

    不要意淫了,这是不可能的.

    单线程异步回调,无阻塞IO 带给我们高性能体验的时候,也埋下了无数的坑,这就是一个比较深的,上帝总是公平的,给了你一个强有力的长矛,就不会再给你坚而不催的盾.

    当 uncaughtException 事件被触发时,已经经过了几次异步回调,冒泡了多少回循环,恐怕它自己都不清楚.......

    不仅仅是找不错出错的堆栈,而且还失去了当前的上下文,这种情况下,你手上连用户请求链接的 response 对象都没有,如何 send() 出去一句高大上的"服务器正在维护中,请稍后访问"

    process.on('uncaughtException', function(err){
    
            //所以这里的回调你不要妄想太多,打算打印一下错误信息还是可以的 
    
            console.log(err); //注意这个错误信息并没有错误发生时的堆栈信息
    
            //然后你还可以做一些手脚,优雅的退出
    
    });
    

    如何避免走到 uncaughtException 这一步?

    很简单,就是把每一个错误捕捉住

    说起来简单,做起来非常难!

    每一个程序员可以拍着胸口说我写的程序没有bug,每一个异常都做了捕捉,想必是不可能的,就算你的代码很健壮,你引用的模块就不会引发一个异常吗?

    那我们是不是在每一处调用 try ... catch

    不完全是, try ... catch 是可以捕捉异常,但是限于当前执行堆栈,直观的理解就是同步运行的代码是有效的,如下

    var num=function(p){
        try{
            return parseInt(p);
        }catch(e){
            console.log(e);
            return 0;
        }
    }
    

    但是异步执行环境下,try .... catch 并不能捕捉,因为异常是发生在当前执行堆栈之外,如下:

    var num=function(p){
        try{
            parse_num(p,function(err,p1){
                if(!err)
                    return p1;
                else
                    return 0;
            });
        }catch(e){
            console.log(e);
            return 0;
        }
    }
    

    上面 try 部分中调用 函数 parse_num ,此函数异步回调返回了 err 和 转化参数 p1 ,但是在异步调用过程中转化数字出现异常,对于 try . ... catch 是未知的.这时他们就无能为力了.

    还好,你遇到的问题大家都遇到了,开源大牛们致力把工具做到十全十美,让我们这些使用的小白简单易用,所以 domain 模块出现了.

  • 相关阅读:
    DDD:四色原型中Role的 “六” 种实现方式
    .NET:脏读、不可重复读和幻读测试
    AIR:使用 HTML + Javascript 开发桌面应用
    Silverlight:《Pro Silverlight5》读书笔记 之 Layout
    设计原则:什么样的情况下需要引入父类?
    设计原则:不要为了复用而使用继承
    Ruby:字符集和编码学习总结
    .NET:字符集和编码学习总结
    Ruby:Sublime中开发Ruby需要注意的Encoding事项
    .NET:遇到并发问题,什么样的情况下需要自动重试?
  • 原文地址:https://www.cnblogs.com/ysk123/p/9848540.html
Copyright © 2011-2022 走看看