异常处理

异常处理

不熟悉 erlang,不过 joyent 这篇讲 node.js 错误处理的文章挺有 let it crash 精髓: 《Joyent | Error Handling**

首先文章定义了 Operational Errors 和 Programmer Errors:

  • Operational Error:表示一个正确的程序在运行时报告的错误;这些错误不是程序本身的 bug,而可能是操作系统的报错、网络错误、用户输入不正确、超时、500、内存不足等;
  • Programmer Error:一般属于程序中的 bug,比如错误的访问 undefined 对象、错误的类型传递;

有时两者会出于同一个 root cause 而一体两面地出现:如果一个服务端出现 bug 导致崩溃,客户端收到 500 将视为 Operational Error;如果对 Operational Error 的处理不正确,这也属于 Programmer Errror。

两者的重要差异在于:Operational Error 是一个正确的程序必须要处理的;而 Programmer Error 属于 bug,程序本身并不能处理。

那么遇到 Programmer Error 应当怎么办呢?这就引出了 Let it crash 策略。

有些 web 框架在请求中遇到 Programmer Error 的异常之后,会吞掉异常继续响应请求,这很常见,但是异常之后可能已经有奇怪的地方变得不一样了:

  • 部分公共状态可能被污染为 null、undefined;
  • 数据库连接可能泄露,甚至可能留着一个未关闭的事务;
  • socket 可能没有正确关闭;
  • 内存可能泄露;

这些错误往往有累加效应,到最终展露症状时就很难找 root cause 了。比如,当你数据库被日积月累的连接泄露连爆的时候,引入这个连接泄露的变更在哪个 commit?

文章认为从 Programmer Error 恢复的最佳方法便是立即 crash,配合一个 supervisor 之类的 restarter,出现问题时立即 crash,并重启恢复到一个干净的初始状态。此外,服务端的 Programmer Error 应被客户端视为 Operational Error,客户端应当对此作处理。