很多 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
其實是 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進程
CentOS編譯安裝MongoDB http://www.linuxidc.com/Linux/2012-02/53834.htm
CentOS 編譯安裝 MongoDB與mongoDB的php擴展 http://www.linuxidc.com/Linux/2012-02/53833.htm
CentOS 6 使用 yum 安裝MongoDB及服務器端配置 http://www.linuxidc.com/Linux/2012-08/68196.htm
Ubuntu 13.04下安裝MongoDB2.4.3 http://www.linuxidc.com/Linux/2013-05/84227.htm
MongoDB入門必讀(概念與實戰並重) http://www.linuxidc.com/Linux/2013-07/87105.htm
Ubunu 14.04下MongoDB的安裝指南 http://www.linuxidc.com/Linux/2014-08/105364.htm
《MongoDB 權威指南》(MongoDB: The Definitive Guide)英文文字版[PDF] http://www.linuxidc.com/Linux/2012-07/66735.htm
Nagios監控MongoDB分片集群服務實戰 http://www.linuxidc.com/Linux/2014-10/107826.htm
基於CentOS 6.5操作系統搭建MongoDB服務 http://www.linuxidc.com/Linux/2014-11/108900.htm
MongoDB 的詳細介紹:請點這裡
MongoDB 的下載地址:請點這裡