初識nodeJS

前面的話

  幾年前,對於學習NodeJS可能還有所遲疑,怕分散了前端學習的精力。但到了如今,若是不學習nodeJS,前端的學習卻可能沒法再有所進展。技術的進步就是這麼殘酷。對新技術觀望的時候,該技術已經大行其道了。本文將介紹nodeJS的基礎知識前端

 

語言選擇

  Ryan Dahl是一名資深的C/C++程序員,在創造出Node以前,他的主要工做都是圍繞高性能 Web服務器進行的。經歷過一些嘗試和失敗以後,他找到了設計高性能,Web服務器的幾個要點: 事件驅動、非阻塞I/O,而這也正是nodejs的兩大特色node

  因此Ryan Dahl最初的目標是寫一個基於事件驅動、非阻塞I/O的Web服務器,以達到更高的性能,提供Apache等服務器以外的選擇。寫Node的時候,Ryan Dahl曾經評估過C、Lua、Haskell、 Ruby等語言做爲備選實現,結論爲:C的開發門檻高,能夠預見不會有太多的開發者能將它用於平常的業務開發,因此捨棄它;Ryan Dahl以爲本身還不足夠玩轉Haskell,因此捨棄它;Lua自身已經含有不少阻塞I/O庫,爲其構建非阻塞I/O庫也不能改變人們繼續使用阻塞I/O庫的習慣,因此也捨棄它;而Ruby的虛擬機因爲性能很差而落選程序員

  相比之下,JavaScript比C的開發門檻要低,比Lua的歷史包袱要少。儘管服務器端JavaScript存在已經不少年了,可是後端部分一直沒有市場,能夠說歷史包袱爲零,爲其導入非阻塞I/O庫沒有額外阻力。另外,JavaScript在瀏覽器中有普遍的事件驅動方面的應用,暗合Ryan Dahl喜愛基於事件驅動的需求。當時,第二次瀏覽器大戰也漸漸分出高下,Chrome瀏覽器的JavaScript引擎V8摘得性能第一的桂冠。考慮到高性能、符合事件驅動、沒有歷史包袱這3個主要緣由,JavaScript成爲了Node的實現語言web

 

起名

  起初,Ryan Dahl稱他的項目爲web.js,就是一個Web服務器,可是項目的發展超過了他最初單純開發一個Web服務器的想法,變成了構建網絡應用的一個基礎框架,這樣能夠在它的基礎上構建更多的東西,諸如服務器、客戶端、命令行工具等。Node發展爲一個強制不共享任何資源的單線程、單進程系統,包含十分適宜網絡的庫,爲構建大型分佈式應用程序提供基礎設施,其目標也是成爲一個構建快速、可伸縮的網絡應用平臺。它自身很是簡單,經過通訊協議來組織許多Node,很是容易經過擴展來達成構建大型網絡應用的目的。每個Node進程都構成這個網絡應用中的一個節點,這是它名字所含意義的真諦編程

 

特色

  做爲後端JavaScript的運行平臺,Node保留了前端瀏覽器JavaScript中那些熟悉的接口,沒有改寫語言自己的任何特性,依舊基於做用域和原型鏈,區別在於它將前端中普遍運用的思想遷移到了服務器端。Node相較於其餘語言的特色以下所示後端

  一、異步I/O瀏覽器

  在Node中,絕大多數的操做都以異步的方式進行調用。Ryan Dahl排除萬難,在底層構建了不少異步I/O的API,從文件讀取到網絡請求等,均是如此。這樣的意義在於,在Node中,咱們可 以從語言層面很天然地進行並行I/O操做。每一個調用之間無須等待以前的I/O調用結束。在編程模型上能夠極大提高效率服務器

  以同時執行兩個文件讀取任務爲例,異步I/O取決於最慢的那個文件讀取的耗時,而同步I/O的耗時是兩個任務的耗時之和。這裏異步帶來的優點是顯而易見的網絡

  二、事件多線程

  隨着Web 2.0時代的到來,JavaScript在前端擔任了更多的職責,事件也獲得了普遍的應用。 Node不像Rhino那樣受Java的影響很大,而是將前端瀏覽器中應用普遍且成熟的事件引入後端, 配合異步I/O,將事件點暴露給業務邏輯

  事件的編程方式具備輕量級、鬆櫚合、只關注事務點等優點,可是在多個異步任務的場景下,事件與事件之間各自獨立,如何協做是一個問題

  三、回調函數

  與其餘的Web後端編程語言相比,Node除了異步和事件外,回調函數是一大特點。縱觀下來,回調函數也是最好的接受異步調用返回數據的方式。可是這種編程方式對於不少習慣同步思路編程的人來講,也許是十分不習慣的。代碼的編寫順序與執行順序並沒有關係,這對他們可能形成閱讀上的障礙。在流程控制方面,由於穿插了異步方法和回調函數,與常規的同步方式相比,變得不那麼一目瞭然了

  四、單線程

  JavaScript語言的一大特色就是單線程,也就是說,同一個時間只能作一件事。JavaScript的單線程,與它的用途有關。做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM。這決定了它只能是單線程,不然會帶來很複雜的同步問題。好比,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另外一個線程刪除了這個節點,這時瀏覽器應該以哪一個線程爲準?因此,爲了不復雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵

  Node保持了JavaScript在瀏覽器中單線程的特色。並且在Node中,JavaScript與其他線程是沒法共享任何狀態的。單線程的最大好處是不用像多線程編程那樣到處在乎狀態的同步問題,這裏沒有死鎖的存在,也沒有線程上下文交換所帶來的性能上的開銷

  一樣,單線程也有它自身的弱點,具體有如下3方面:沒法利用多核CPU;錯誤會引發整個應用退出,應用的健壯性值得考驗;大量計算佔用CPU致使沒法繼續調用異步I/O

  像瀏覽器中JavaScript與UI共用一個線程同樣,JavaScript長時間執行會致使UI的渲染和響應被中斷。在Node中,長時間的CPU佔用也會致使後續的異步I/O發不出調用,已完成的異步I/O的回調函數也會得不到及時執行

  HTML5定製了Web Workers的標準,Web Workers可以建立工做線程來進行計算,以解決JavaScript大計算阻塞UI渲染的問題。工做線程爲了避免阻塞主線程,經過消息傳遞的方式來傳遞運行結果,這也使得工做線程不能訪問到主線程中的UI

  Node採用了與Web Workers相同的思路來解決單線程中大計算量的問題:child_process。 子進程的出現,意味着Node能夠從容地應對單線程在健壯性和沒法利用多核CPU方面的問題。經過將計算分發到各個子進程,能夠將大量計算分解掉,而後再經過進程之間的事件消息來傳遞結果,這能夠很好地保持應用模型的簡單和低依賴。經過Master-Worker的管理方式,也能夠很好地管理各個工做進程,以達到更高的健壯性

 

應用場景

  在進行技術選型以前,須要瞭解一項新技術具體適合什麼樣的場景,畢竟合適的技術用在合適的場景能夠起到意想不到的效果。關於Node,探討得較多的主要有I/O密集型和CPU密集型

  一、I/O密集型

  若是將全部的腳本語言拿到一處來評判,那麼從單線程的角度來講,Node處理I/O的能力是值得豎起拇指稱讚的。一般, 說Node擅長I/O密集型的應用場景基本上是沒人反對的。Node面向網絡且擅長並行I/O,可以有效地組織起更多的硬件資源,從而提供更多好的服務

  I/O密集的優點主要在於Node利用事件循環的處理能力,而不是啓動每個線程爲每個請求服務,資源佔用極少

  二、CPU密集型

  換一個角度,在CPU密集的應用場景中,Node是否能勝任呢?實際上,V8的執行效率是十分高的。單以執行效率來作評判,V8的執行效率是毋庸置疑的

  CPU密集型應用給Node帶來的挑戰主要是:因爲JavaScript單線程的緣由,若是有長時間運行的計算(好比大循環),將會致使CPU時間片不能釋放,使得後續I/O沒法發起。可是適當調整和分解大型運算任務爲多個小任務,使得運算可以適時釋放,不阻塞I/O調用的發起,這樣既可同時享受到並行異步I/O的好處,又能充分利用CPU

相關文章
相關標籤/搜索