前言
本綜述文章旨在幫助讀者深刻理解下Node.js的本質,不去關注應用的細節,我認爲真正的技術問題只有在動手寫代碼的時候纔會遇到,那個階段解決問題纔是真正有意義的。
發展史
Node.js是Ryan Dahl 2009年對外發布的開源醒目,後來該項目被Joyent公司注意到並於2010年成爲Joyent公司的一個子項目。2016年微軟與Joyent公司合做,Node.js在windows上獲得支持。
目前Node.js的版本爲V6.11,周圍已經造成了一個龐大的生態系統。
特性分析
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
上面是Node.js的官方描述,其中包含了Node.js最突出的特色。
一、Javascript runtime
這個描述解答了Node.js是什麼的問題。它是一個Javascript 運行環境,相似於JVM之於Java,Node.js負責將Javascript轉化爲計算機能夠識別的機器語言,同時對外提供API。傳統上javascript依附於瀏覽器運行:
Node.js捨棄了瀏覽器,直接與js引擎對接,經過js引擎提供的API,Node.js能夠完成其餘後端語言(java)所能完成的一切功能,例如文件操做、網絡通訊、設備管理等等。
下面說下Node.js所採用的js引擎——V8,這是目前世界上最快的js引擎,來自於Google Chrome項目,用C++語言編寫,憑藉Goole強大的技術支持,它的執行速度已經接近本地代碼的執行速度。
除了V8之外,Node.js的仍是用了libev和libio庫支持事件驅動和異步IO,如圖所示,libuv是在libev和libeio的基礎上抽象出的一層,對於POSIX系統,libuv利用epoll或者kqueue,而在Windows系統中,libuv使用了IOCP機制,以在不一樣的平臺下實現統一的高性能。
二、non-blocking IO and event-driven
先說說非阻塞IO,假設一個請求要讀取數據庫,db.query(select * from table),這個過程涉及磁盤讀取與網絡通訊,耗時很長,下面是幾種服務器處理方式。
(1)若是是單線程+阻塞處理,線程會等待數據讀取完畢才繼續處理,同時後續的請求也得等待,這樣的系統是不能忍受的。
(2)好在如今的後端容器都是支持多線程+阻塞的,其解決思路以下:
等待數據的線程繼續等待,若是有新請求就從新建立一個線程,把cpu讓給新的線程,待原線程獲得數據後再把cpu切換給原線程。這樣作有什麼缺點麼?
一是大量請求的狀況下線程數目不斷增長,浪費大量系統資源。
二是CPU在處理上下文切換的時候也浪費了很多時間。
(3)Node.js的解決思路則徹底不同。它被設計成單線程+非阻塞的。
全部的請求都在一個線程處理,一旦遇到耗時的請求,cpu不等待數據返回,而是接着處理後續的請求。那麼問題來了,前面請求的數據到達後,如何返回給前端呢?這就要牽扯到Node.js的另一個特性——事件驅動。
在上面的簡化模型中,全部的請求會依次進入線程的處理循環中,每一個請求自帶回調函數,當耗時請求接受完數據後,回調函數自動被調用,從新進去循環處理,直到數據被返回給前端。
這樣能讓單個CPU充分運行起來,沒有絲毫等待,同時避免了在不一樣的線程中頻繁切換引發的浪費。根據統計,Node.js相對傳統的PHP+Nginx,在性能上有明顯提高。
這種設計思路就是爲微服務web系統而生的,由於web服務的特色就是請求密集、計算量小、要求快速響應。
Node.js的缺點
一、對於長期佔據CPU的請求,後續的請求不能獲得及時處理,產生較大延時,因此Node.js不適合計算密集型應用。
二、Node.js專一單線程處理,在多核環境中,必須總多進城才能充分利用多核,所以增長了設計難度。
三、Node.js的異步式編程模式不太符合通常的程序控制思路,給編碼和調試帶來很多困難。
經常使用輔助框架
一、npm(Node Package Manager)javascript
Node.js自己提供的API比較底層,徹底依靠Node.js實現一個系統對技術人員要求比較高。不過如今已經有大量的第三方支持供開發者使用。爲了更好地使用和管理這些第三方提供的包,Node.js官方提供了一個基於命令行的包管理工具——npm.前端
npm徹底由javascript實現,不屬於Node.js的一部分。不過在Node.js0.6開始,npm會自動包含在發行版中。java
二、Expressweb
參考
《Node.js開發指南》
《爲何我要用 Node.js》http://blog.jobbole.com/53736/