本章導讀
NodeJS發(fā)展史
2009年5月鞋囊, Ryan Dahl在GitHub上發(fā)布了基于V8引擎的NodeJS最初的?本。目前NodeJS的官方網站是: http://nodejs.org徐鹤。NodeJS還符合高性能Web服務器的設計要求:事件驅動和非阻塞IO,因此邀层,得到了極大的推崇和發(fā)展返敬。
注意:V8是JS引擎,webkit是布局引擎寥院。因此劲赠,node與前端js一樣,也是基于作用域和原型鏈的秸谢。
Node的特點
異步IO
我們來看一個異步IO的例子
var fs = require('fs');
fs.readFile('/path', function (err, file) {
console.log('讀完文件?成')
});
console.log('開始讀文件');
異步IO比同步IO消耗更少的時間(因為凛澎,異步IO可以讓多個任務同時在多個進程中處理,同步IO只有完成一個任務處理之后估蹄,才會進行下一個任務)塑煎,更大限度的使用CPU的資源。
事件與回調函數(callback)
事件編程的好處是只關注事務臭蚁,確保程序在正確的時間執(zhí)行最铁。同時讯赏,通過回調函數,將各個事件之間關聯起來冷尉。
跨平臺
WIN漱挎、*inx、MacOS上都能用
單線程
每個Node實例都是單線程處理程序的雀哨,不同線程之間無法共享狀態(tài)磕谅。因此,不存在線程鎖(死鎖也就不存在嘍)和上下文線程交換所帶來的性能上的開銷雾棺。
相應的缺點就是膊夹,單一node實例無法利用多核cpu,程序健壯性需要控制捌浩,防止因為一個錯誤造成整個服務的宕機放刨,大量占用cpu的操作可能會引起異步io無法執(zhí)行。不過嘉栓,這個是以前的情況了宏榕,現在通過反向代理、負載均衡侵佃、clustor麻昼、web wokers等可以最大限度的降低這些問題的發(fā)生。
nodejs還提供了與web workers相同的思路的解決方案馋辈,child_process(子進程抚芦,將計算分發(fā)到子進程,可以將大量的計算分解掉迈螟。然后叉抡,再通過進程間的事件消息來傳遞結果,這可以很好地保持應用模型的簡單和低依賴答毫。這就是Master-Worker的管理方式褥民,這個方式很好地管理各個工作進程,創(chuàng)造出更好的程序健壯性洗搂。)
Node的應用場景
IO密集型
因為事件驅動和異步IO消返,因此,對于IO的吞吐量是巨大的耘拇。
CPU密集型
其實Node挺快的了撵颊,還可以通過擴展C/C++模塊,來提升性能惫叛。
這里我們通過分析不同語言在執(zhí)行菲波那切數列(F0=0倡勇,F1=1,Fn=F(n-1)+F(n-2)(n>=2))的效率和性能嘉涌,來說明一下妻熊。(此處設置n=40夸浅,這個測試主要偏重于cpu棧操作,其中固耘,c和go都是靜態(tài)語言题篷,用于參考)
通過這個表格词身,我們可以看出厅目,node也具有優(yōu)秀的cpu計算能力,這個能力主要來源于V8引擎的深度優(yōu)化法严,也就是說通過對于node內核的C/C++的調優(yōu)损敷,node是可以獲得非常牛的運算能力的。(其實深啤,關于cpu密集型的運算在node上存在這樣一個問題拗馒,因為,node是單線程的溯街,如果長時間運行技術诱桂,例如大的循環(huán),將會導致cpu時間片不能釋放呈昔,使得后續(xù)IO無法發(fā)起挥等,但是可以通過適當調整和分解大型運算任務,將其分解為一個個小的運算堤尾,使得運算能夠適時釋放肝劲,不阻塞IO調用的發(fā)起就可以了)
綜上所述,node解決cpu密集型問題也有兩個方案
方案一:通過編寫C/C++擴展的方式更高效的利用CPU郭宝,將一些V8不能做到性能極致的地方通過C/C++來實現辞槐。
方案二:啟用子進程,將一部分node進程當做常駐服務進程用于計算粘室,然后利用進程間的消息傳遞結果榄檬,將計算與IO分離,這樣還可以更進一步的壓榨CPU衔统。
另外鹿榜,在第四章,作者簡單介紹了如何拆分和調度任務以到達將大任務拆分的目的缰冤,也就是:如何分解任務的方法來應對cpu密集型的程序:(這部分內容在第四章的筆記中也有寫犬缨,此處做一個冗余處理)
由于事件循環(huán)模型需要應對海量請求,海量請求同時作用在單線程上棉浸,就需要防止任何一個計算耗費過多的cpu時間片怀薛。至于是計算密集型,還是IO密集型迷郑,只要計算不影響異步IO的調度枝恋,那就不構成問題创倔。建議對cpu的耗用不要超過10ms,或者將大量的計算分解為諸多的小量計算焚碌,通過setImmediate()進行調度畦攘。只要合理利用node的異步模型與V8的高性能,就可以充分發(fā)揮cpu和IO資源的優(yōu)勢十电。
與遺留系統(tǒng)和平相處
用node做個中間層知押。
分布式應用
阿里巴巴的數據平臺對Node的分布式應用算是一個典型的例子。分布式應用意味著對可伸縮性的要求非常高鹃骂。數據平臺通常要在一個數據庫集群中去尋找需要的數據台盯。阿里巴巴開發(fā)了中間層應用NodeFox、ITier畏线,將數據庫集群做了劃分和映射静盅,查詢調用依舊是針對單張表進行SQL查詢,中間層分解查詢SQL寝殴,并行地去多臺數據庫中獲取數據并合并蒿叠。NodeFox能實現對多臺MySQL數據庫的查詢,如同查詢一臺MySQL一樣蚣常,而ITier更強大市咽,查詢多個數據庫如同查詢單個數據庫一樣,這里的多個數據庫是指不同的數據庫史隆,如MySQL或其他各種類型的數據庫魂务。這個案例也是高效利用并行IO地例子,也是高效使用數據庫的過程泌射。對于node來說只是一次普通的IO粘姜,對于數據庫而言,卻是一次復雜的計算熔酷,所以也是進而充分壓榨硬件資源的過程孤紧。
基于socket.io的長連接應用
例如游戲服務器、即時通訊服務器拒秘。