【深入Node探究】(1)“Node特點與應(yīng)用場景” 有四問
1、為什么叫Node?
它自身非常簡單,通過通信協(xié)議來組織很多Node,非常容易通過擴展來達成構(gòu)建大型網(wǎng)絡(luò)應(yīng)用的目的。每一個Node進程都構(gòu)成這個網(wǎng)絡(luò)應(yīng)用中的一個節(jié)點,這是它名字所含意義的真諦。
2、你能說說Node的特點嗎?
作為后端JavaScript的運行平臺,Node保留了前端瀏覽器JavaScript中那些熟悉的接口,沒有改寫語言本身的任何特性,依舊基于作用域和原型鏈,區(qū)別在于它將前端中廣泛運用的思想遷移到了服務(wù)器端。下面我們可以看看node相較于其他語言的一些特點:
(1)異步I/O
關(guān)于異步I/O,向前端工程師解釋起來或許會容易一些,因為發(fā)起Ajax調(diào)用對于前端工程師而言是再熟悉不過的場景了。下面的代碼用于發(fā)起一個Ajax請求:
- $.post('/url', {title: ’深入淺出Node.js'}, function (data) {
- console.log(’收到響應(yīng)’);
- });
- console.log(’發(fā)送Ajax結(jié)束’);
熟悉異步的用戶必然知道,“收到響應(yīng)”是在“發(fā)送Ajax結(jié)束”之后輸出的。在調(diào)用$.post()后,后續(xù)代碼是被立即執(zhí)行的,而“收到響應(yīng)”的執(zhí)行時間是不被預(yù)期的。我們只知道它將在這個異步請求結(jié)束后執(zhí)行,但并不知道具體的時間點。異步調(diào)用中對于結(jié)果值的捕獲是符合“Don't call me, I will call you”的原則的,這也是注重結(jié)果,不關(guān)心過程的一種表現(xiàn)。
(2)事件與回調(diào)函數(shù)
Node不像Rhino那樣受Java的影響很大,而是將前端瀏覽器中應(yīng)用廣泛且成熟的事件引入后端,配合異步I/O,將事件點暴露給業(yè)務(wù)邏輯。
相比之下,無論在前端還是后端,事件都是常用的。對于其他語言來說,這種俯拾皆是JavaScript的熟悉感覺是基本不會出現(xiàn)的。
(3)單線程
Node保持了JavaScript在瀏覽器中單線程的特點。而且在Node中,JavaScript與其余線程是無法共享任何狀態(tài)的。
單線程的最大好處是不用像多線程編程那樣處處在意狀態(tài)的同步問題,這里沒有死鎖的存在,也沒有線程上下文交換所帶來的性能上的開銷。
同樣,單線程也有它自身的弱點,這些弱點是學習Node的過程中必須要面對的。積極面對這些弱點,可以享受到Node帶來的好處,也能避免潛在的問題,使其得以高效利用。單線程的弱點具體有以下3方面。
- ❑ 無法利用多核CPU。
- ❑ 錯誤會引起整個應(yīng)用退出,應(yīng)用的健壯性值得考驗。
- ❑ 大量計算占用CPU導致無法繼續(xù)調(diào)用異步I/O。
像瀏覽器中JavaScript與UI共用一個線程一樣,JavaScript長時間執(zhí)行會導致UI的渲染和響應(yīng)被中斷。在Node中,長時間的CPU占用也會導致后續(xù)的異步I/O發(fā)不出調(diào)用,已完成的異步I/O的回調(diào)函數(shù)也會得不到及時執(zhí)行。
3、上面提到單線程不利于計算,無法利用多核cpu,難道沒有解決方法嗎?
有的。
Node采用了與Web Workers相同的思路來解決單線程中大計算量的問題:child_process。
子進程的出現(xiàn),意味著Node可以從容地應(yīng)對單線程在健壯性和無法利用多核CPU方面的問題。通過將計算分發(fā)到各個子進程,可以將大量計算分解掉,然后再通過進程之間的事件消息來傳遞結(jié)果,這可以很好地保持應(yīng)用模型的簡單和低依賴。
4、那你可以談?wù)刵ode的使用場景嗎?
關(guān)于Node,探討得較多的主要有I/O密集型和CPU密集型。
I/O密集型
在Node的推廣過程中,無數(shù)次有人問起Node的應(yīng)用場景是什么。如果將所有的腳本語言拿到一處來評判,那么從單線程的角度來說,Node處理I/O的能力是值得豎起拇指稱贊的。通常,說Node擅長I/O密集型的應(yīng)用場景基本上是沒人反對的。Node面向網(wǎng)絡(luò)且擅長并行I/O,能夠有效地組織起更多的硬件資源,從而提供更多好的服務(wù)。
I/O密集的優(yōu)勢主要在于Node利用事件循環(huán)的處理能力,而不是啟動每一個線程為每一個請求服務(wù),資源占用極少。
CPU密集型
換一個角度,在CPU密集的應(yīng)用場景中,Node是否能勝任呢?實際上,V8的執(zhí)行效率是十分高的。單以執(zhí)行效率來做評判,V8的執(zhí)行效率是毋庸置疑的。
CPU密集型應(yīng)用給Node帶來的挑戰(zhàn)主要是:由于JavaScript單線程的原因,如果有長時間運行的計算(比如大循環(huán)),將會導致CPU時間片不能釋放,使得后續(xù)I/O無法發(fā)起。但是適當調(diào)整和分解大型運算任務(wù)為多個小任務(wù),使得運算能夠適時釋放,不阻塞I/O調(diào)用的發(fā)起,這樣既可同時享受到并行異步I/O的好處,又能充分利用CPU。
CPU密集不可怕,如何合理調(diào)度是訣竅。
最后
這是我策劃撰寫的關(guān)于深入探討node的系列文章