Node.js到底是什麼? html
Node.js到底是什麼?
做者:koala 一個有趣的人
文章同步到github博客:https://github.com/koala-coding/goodBlog前端
前言node
若是你有必定的前端基礎,好比 `HTML、CSS、JavaScript、jQuery;那麼,Node.js 能讓你以最低的成本快速過渡成爲一個全棧工程師(我稱這個全棧爲僞全棧,我認爲的全棧也要精通數據庫,不喜勿噴),從而觸及後端和移動端的開發。固然,Node.js也不是萬能的、也不是說學了它就能夠徹底取代後端的其餘開發語言,它有本身的使命和擅長的應用領域。git
除此以外如今很是火熱的 Vue.js,Rect.js ,等不少數據層動態交互優先選用了Node.js,一些比較流行的打包工具也是如此;綜上,爲你爲何要學習它又增長了一大理由。程序員
Node.js 和傳統的後端語言(好比PHP、JAVA等)相比,各有優缺點,各自擅長領域和側重點不一樣,所以,各有千秋、各有需求市場。Node.js 讓咱們進行後端開發多了一種便捷的手段。因此你們也不要總說哪些語言是最好的,各有各的使命,嘿嘿。github
Node.js的特色web
非阻塞異步io面試
例如,當在訪問數據庫取得數據的時候,須要一段時間。在傳統的單線程處理機制中,在執行了訪問數據庫代碼以後,整個線程都將暫停下來,等待數據庫返回結果,才能執行後面的代碼。也就是說,I/O阻塞了代碼的執行,極大地下降了程序的執行效率。數據庫
因爲 Node.js 中採用了非阻塞型I/O機制,所以在執行了訪問數據庫的代碼以後,將當即轉而執行其後面的代碼,把數據庫返回結果的處理代碼放在回調函數中,從而提升了程序的執行效率。npm
當某個I/O執行完畢時,將以事件的形式通知執行I/O操做的線程,線程執行這個事件的回調函數。爲了處理異步I/O,線程必須有事件循環,不斷的檢查有沒有未處理的事件,依次予以處理。
阻塞模式下,一個線程只能處理一項任務,要想提升吞吐量必須經過多線程。而非阻塞模式下,一個線程永遠在執行計算操做,這個線程的CPU核心利用率永遠是100%。因此,這是一種特別有哲理的解決方案:與其人多,可是好多人閒着;還不如一我的玩命,往死裏幹活兒。
單線程
在 Java、PHP 或者 .net 等服務器端語言中,會爲每個客戶端鏈接建立一個新的線程。而每一個線程須要耗費大約2MB內存。也就是說,理論上,一個8GB內存的服務器能夠同時鏈接的最大用戶數爲4000個左右。要讓Web應用程序支持更多的用戶,就須要增長服務器的數量,而 Web 應用程序的硬件成本固然就上升了。
Node.js不爲每一個客戶鏈接建立一個新的線程,而僅僅使用一個線程。當有用戶鏈接了,就觸發一個內部事件,經過非阻塞I/O、事件驅動機制,讓 Node.js 程序宏觀上也是並行的。使用 Node.js ,一個8GB內存的服務器,能夠同時處理超過4萬用戶的鏈接。
另外,單線程帶來的好處,操做系統徹底再也不有線程建立、銷燬的時間開銷。可是單線程也有不少弊端,會在 Node.js 的弊端詳細講解,請繼續看。
事件驅動
在 Node 中,客戶端請求創建鏈接,提交數據等行爲,會觸發相應的事件。在 Node 中,在一個時刻,只能執行一個事件回調函數,可是在執行一個事件回調函數的中途,又有其餘事件產生,能夠轉而處理其餘事件(好比,又有新用戶鏈接了),而後返回繼續執行原事件的回調函數,這種處理機制,稱爲「事件環」機制。
Node.js 底層是 C++(V8也是C++寫的)。底層代碼中,近半數都用於事件隊列、回調函數隊列的構建。用事件驅動來完成服務器的任務調度,這是鬼才才能想到的。針尖上的舞蹈,用一個線程,擔負起了處理很是多的任務的使命。
注意這裏的事件循環,也能夠說是 Node.js 的一個精髓所在,下面引用一段 Node.js 官網的內容
┌───────────────────────────┐ ┌─>│ timers │ │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ │ │ pending callbacks │ │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ │ │ idle, prepare │ │ └─────────────┬─────────────┘ ┌───────────────┐ │ ┌─────────────┴─────────────┐ │ incoming: │ │ │ poll │<─────┤ connections, │ │ └─────────────┬─────────────┘ │ data, etc. │ │ ┌─────────────┴─────────────┐ └───────────────┘ │ │ check │ │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ └──┤ close callbacks │ └───────────────────────────┘
引用Node官網中的一段內容:
注意:每一個框將被稱爲事件循環的「階段」。
每一個階段都有一個要執行的回調FIFO隊列。雖然每一個階段都以其本身的方式特殊,但一般狀況下,當事件循環進入給定階段時,它將執行特定於該階段的任何操做,而後在該階段的隊列中執行回調,直到隊列耗盡或最大回調數量爲止已執行。當隊列耗盡或達到回調限制時,事件循環將移至下一階段,依此類推。
關於事件循環是一個核心點,常常會被面試官考具體執行輸出的問題,你們能夠看個人這篇文章
跨平臺
起初,Node 只能在 Linux 平臺上運行。後來隨着Node的發展,微軟注意到了它的存在,並投入了一個團隊幫助 Node 實現 Windows 平臺的兼容,在v0.6.0版本發佈時,Node 已經可以直接在 Window 平臺運行了。 Node 是基於libuv實現跨平臺的。
Node.js的弊端
單線程帶來的弊端
Node.js中有一個特色就是單線程,它帶來了不少好處,可是它也有弊端,單線程弱點以下。
以上確實是Node的弊端,可是都會有一些對應的解決方案:
弊端1:解決方案
弊端2:解決方案
弊端3:解決方案
說明:child_process與cluster模塊我會單獨拿一篇文章來說。
值得開心的是上面這些弊端隨着Node的版本更新,和新的api模塊出現,好像解決了這些弊端。
調試
用過node的人可能第一時間就會想到debug太難了,沒有stack trace,所以調試比較困難。
Node社區中的npm包
Node.js社區有不少包品質參差不齊、若是你想偷懶而又恰好npm了一個有問題的包你就很麻煩,由於代碼是開源的,只能本身調試了。
Node.js的應用場景
介紹了Node.js的特色和弊端,再說一下Node.js的應用場景。
Node.js適合用來開發什麼樣的應用程序呢?
善於I/O,不善於計算。由於Node.js最擅長的就是任務調度,若是你的業務有不少的 CPU 計算,實際上也至關於這個計算阻塞了這個單線程,就不太適合Node開發,可是也不是沒有解決方案,只是說不太適合。
當應用程序須要處理大量併發的I/O,而在向客戶端發出響應以前,應用程序內部並不須要進行很是複雜的處理的時候,Node.js很是適合。Node.js也很是適合與web socket配合,開發長鏈接的實時交互應用程序。
具體場景能夠表現爲以下:
哪些大公司在用
參考文章:本文部份內容來自樸靈老師的《深刻淺出Node.js》
文章同步到
程序員成長指北(ID:coder_growth)