摘要 本文針對在Node.js關鍵的兩個概念:非阻塞IO和事件循環進行了適當的總結。
目錄
非阻塞的IO模型
事件循環 event loop
小結
學習和使用Node.js已經有兩個月,使用express結合mongoose寫了一個web應用和一套RESTful web api,回過頭來看Node.js官網首頁對Node.js的介紹:Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.那麼其中的non-blocking I/O model 意味著什麼呢?
首先,IO操作無疑是耗時的,當服務器端接收到大量請求時,為每一個請求創建進程或線程的同時,也增加了額外的內存開銷,也可能浪費更多的時間資源。
由於Node.js是事件驅動的,於是它使用了事件循環來解決IO操作帶來的瓶頸問題。在Node.js中,一個IO操作通常會帶有一個回調函數,當IO操作完成並返回時,就會調用這個回調函數,而主線程則繼續執行接下來的代碼。簡單的用一個例子來說明這個問題:
request('http://www.linuxidc.com', function(error, response, body) {
console.log(body);
});
console.log('Done!');
這段代碼的意思是向'http://www.linuxidc.com'發出請求,當請求返回這則調用回調函數輸出響應信息。由於Node.js的運行機制,這段代碼運行後,會立即在控制台輸出'Done!',然後一段時間後再輸出響應的信息。
接下來,來討論下事件循環的機制。首先說說調用桟,比如有如下一段代碼:
function A(arg, func){
var a = arg;
func();
console.log('A');
}
function B(){
console.log('B');
}
A(0, B);
當代碼執行後,函數A首先被推入調用桟中成為棧頂元素並開始執行A,在執行過程中函數B又被推入調用桟成為棧頂元素,在B執行完成後,B被彈出調用桟,A再次成為棧頂元素,在A執行完成後A被彈出調用桟,調用桟呈空閒狀態。
在Javascript運行時中存在一個消息隊列,而消息和一個回調函數相關聯,當一個事件被觸發時,如果這個事件有相應的回調函數,則該消息就會被加入到消息隊列中去。
回過頭來說事件循環到底循環的是什麼,在代碼開始執行後,函數被不斷推入調用桟中,就拿上面的例子來講,request被推入調用桟中,這個函數將進行一個http請求(這個http請求將交由Node.js的底層模塊來實現)同時請求完成的事件和一個回調函數關聯起來,request被彈出調用桟,console.log被推入調用桟開始執行。當請求完成時,完成事件被觸發,一條消息被添加進消息隊列中,消息隊列首先會檢查調用桟是否為空閒狀態,如果調用桟並不空閒,則會一直等待到調用桟空閒狀態後,將消息隊列的頭部彈出,此時與該消息相關聯的回調函數被執行。
以上就無阻塞模型和事件循環在概念上進行了總結。而這個事件循環的機制並不僅僅是Node.js所獨有的,並且Node.js的代碼是單線程執行的,在面對大量並發請求的時候,又有著什麼優勢呢?
上面這張圖展示了Node.js的架構圖,Node.js的底層有一個模塊負責維護線程池,當一個IO請求發出的時候,Node.js的底層模塊將新建一個線程來處理請求,完成後再將結果交還給上層。那麼,當有多個請求的時候,Node.js的底層模塊將利用盡可能少的線程來完成最多的任務,如果存在空閒的線程,它將繼續被利用來做其他的事情,這對於前面說的針對每個請求開一個新的進程或線程而言,無疑“聰明”許多,也更加高效了。
這篇文章是對學習Node.js的一個總結,其中若有問題和不足,歡迎批評指正。
Ubunru 12.04 下Node.js開發環境的安裝配置 http://www.linuxidc.com/Linux/2014-05/101418.htm
Node.Js入門[PDF+相關代碼] http://www.linuxidc.com/Linux/2013-06/85462.htm
Node.js開發指南 高清PDF中文版 +源碼 http://www.linuxidc.com/Linux/2014-09/106494.htm
Node.js入門開發指南中文版 http://www.linuxidc.com/Linux/2012-11/73363.htm
Node.js安裝與配置 http://www.linuxidc.com/Linux/2013-05/84836.htm
Ubuntu 編譯安裝Node.js http://www.linuxidc.com/Linux/2013-10/91321.htm
Node.js 的詳細介紹:請點這裡
Node.js 的下載地址:請點這裡