我與Node.js重新認識的第一週 - Node.js 風格特點

macctown發表於2017-11-14
書接上回,

慢慢悠悠讀了《深入淺出node.js》(後面簡寫作《深淺》)以及《node.js高階程式設計》(後面簡寫作《高階》)的開頭部分,查了不少網路資料,關於node.js的特點有了一定了解。深究起來需要再看看作業系統以及網路的知識。

《深淺》中提到了四個node.js的特點:非同步I/O,事件與回撥函式,單執行緒以及跨平臺。
《高階》中基本是一筆帶過,提到了純事件驅動以及非阻塞。

其中對於非同步I/O以及單執行緒這兩個特性,我認為可以分以下三個方向來概述為什麼node.js把天賦點在了這它們上面?

1. 使用者體驗

從前端載入的角度來看,比較直接。先說為什麼JavaScript用非同步?!我們反著思考,如果JavaScript是同步的,會有什麼問題。請求一個使用者管理頁面,用js載入若干資源,先載入一個使用者頭像,再載入第二個,第三個。。。GG,使用者以為卡死了,二話不說給你關了(《深淺》中提到指令碼時間超過100毫秒,使用者就會有卡頓的感覺;而且執行在單執行緒上的JavaScript還與UI渲染公用一個程式)。實際中,JavaScript的非同步消除/減弱了UI阻塞的現象,同步時候載入資源的總時間是X+Y+Z,非同步下的總時間則是max(X+Y+Z),可見差距。另外《深淺》中來提到目前網路發展,分散式應用普及,前面XYZ的數值在增長,那麼可以想象到X+Y+Z和max(X+Y+Z)的差距肯定越來越大。由此可以看出非同步大法好,大家都說屌!那麼node.js選擇非同步I/O也就順理成章,從後端做到非同步,提升資源響應速度,那麼隨之前端的使用者體驗也就會更好

                                    

2. 系統資源

一組任務需要被執行,可以通過兩種方式:單執行緒序列執行,多執行緒並行執行。

單執行緒序列執行,問題是:同步阻塞! I/O需要等待X步結束,才能進行到X+1步 - 原因是早期分時系統:cpu輪流給不同使用者服務(服務的時間單位是時間片),給A服務完了第x步,可能就去給B服務第y步,之後才又回到屬於給A服務的時間片,然後再給A服務x+1步(這也能看出來為啥I/O需要等待,上一步結束才能執行下一步)。為了繼續執行A的操作,從x到x+1步驟的上下文就需要系統維護和交換,那麼當程式很多,就會造成效能的下降。慢的任務就會拖慢整個處理進度- 這樣難道一無是處麼,並不是,好處是順序程式設計,邏輯比較容易,易於表達 。

多執行緒並行執行,問題是:程式設計時要考慮鎖,狀態同步的問題,稍有不慎,家毀人亡! 

因此,node.js的解決方案是:利用單執行緒,遠離多執行緒死鎖、狀態同步等問題;利用非同步I/O,讓單執行緒遠離阻塞,以更好地使用CPU。(《深淺》原句)

                                 我與Node.js重新認識的第一週 - Node.js 風格特點

3. 應用場景

node.js特點與其應用場景我感覺互為問題與答案,考慮到web app是當今最常見的I/O密集型任務,node.js選擇了非同步I/O,單執行緒以及事件驅動,來增強效能。同時,也正是因為node.js
的這些特點,使得它更加適合I/O密集型的應用場景。(關於node.js是否適合計算密集型任務,《深淺》中做了解釋與對比) 

---------------------------------------------------------------------

下面是另外幾點令我印象深刻的地方:

  • 《深淺》還提到:為了提升效能增加程式數量,這種方法是無法提升資源利用率。他用到了『加三倍伺服器』的例子,下面是我從豆瓣上找到的一個解釋:(加三倍伺服器是否能提升效能)要看系統本身的架構,不一定增加三倍伺服器就能檔得住三倍的使用者一起來點的。因為伺服器增多之後,其間通訊的成本也增加了,而且如果存在中心節點,那麼那幾個節點還是會變成瓶頸。跟高速公路堵車對比,加伺服器並不是“四車道變八車道”那麼簡單,很可能多修幾條路以後1)十字路口也變多了2)支路多了以後主幹道堵得更厲害。” 
  • 如果深究非同步I/O這個東西,《深淺》第三章做了更加細緻的講解,涉及到了非同步的幾種實現方式,以及Node是怎麼實現非同步I/O的。原來之前說的非同步,是理想的非阻塞非同步I/O: 

    我與Node.js重新認識的第一週 - Node.js 風格特點

                                          (出自《深入淺出node.js》)

       真正到了實現的時候,Node其實是用了多執行緒的方式模擬出來這一理想的效果。 

我與Node.js重新認識的第一週 - Node.js 風格特點

                                          (出自《深入淺出node.js》)

     等等,多執行緒?Node不是JavaScript,是單執行緒麼,上面特點不說了是單執行緒麼?是不是說漏嘴了。那必須不是,《深淺》書中提到,Node的單執行緒指的JavaScript執行在單執行緒中,而實現Node的非同步I/O功能的則是執行緒池/多執行緒。 
  • node.js既然有非同步I/O的特點,是不是就可以肆意妄為了,只要非同步就一定非阻塞呢?答案肯定是不啊(考這麼多年試:像這種極端的問題,答案肯定是否定的)。如果我們在主執行緒做過多的任務,或者很多計算密集型任務,那麼可能會導致主執行緒的卡死,影響整個程式的效能,這不就阻塞你非同步的腳步了。


如果有什麼地方總結的不對,希望大家一起交流!


相關文章