第一次更新 查漏補缺昨晚零時寫的 辣雞輸入法導致錯別字太多。
Node.js的到底是用來做什么的
在闡述之前我想放一個鏈接,這是國外的一個大神,對于node.js非常好的一篇介紹的文章,英文比較好的朋友可以直接去閱讀,本文也很大程度上參考了這篇文章,也同時感謝知乎用戶廠長對于本文的翻譯!原文題目為Node.js is the New Black
Node.js的簡介
根據維基百科對于Node.js的介紹,我們可以知道一些基本關于Node.js的情況。Node.js是瑞安·達爾(Ryan Dahl)在2009年發明出來的一種一個能夠在服務器端運行JavaScript,并且可以開放源代碼,以及跨平臺運行JavaScript的一種運行環境。
Node.js采用了Google公司的V8引擎。Node.js允許通過JavaScript和一系列模塊來編寫服務器端應用和網絡相關的應用。核心模塊包括文件系統I/O、網絡(HTTP、TCP、UDP、DNS、TLS/SSL等)、二進制數據流、加密算法、數據流等等。Node模塊的API形式簡單,降低了編程的復雜度。
Node.js主要用于編寫像Web服務器一樣的網絡應用,這和PHP和Python是類似的。但是Node.js與其他語言最大的不同之處在于,PHP等語言是阻塞的(只有前一條命令執行完畢才會執行后面的命令),而Node.js是非阻塞的(多條命令可以同時被運行,通過回調函數得知命令已結束運行)。
Node.js是事件驅動的。開發者可以在不使用線程的情況下開發出一個能夠承載高并發的服務器。其他服務器端語言難以開發高并發應用,而且即使開發出來,性能也不盡人意。Node.js正是在這個前提下被創造出來。Node.js把JavaScript的易學易用和Unix網絡編程的強大結合到了一起。
Node.js使用Google V8 JavaScript 引擎,因為
- V8是基于BSD許可證的開源軟件
- V8速度非???/li>
- V8專注于網絡功能,在HTTP、DNS、TCP等方面更加成熟
Node.js已經有數十萬模塊,它們可以通過一個名為npm的管理器免費下載。Node.js開發社區主要有兩個郵件列表、一個在freenode的名為#node.js的IRC頻道。社區集中在NodeConf。
雜敘
在學習Web前端的朋友看來,Node.js是一個經常會聽到而且無法回避的問題,然而國內的資料相對較少,國外的資料大多數是以英文為主要藍本闡述的,所以友好度并不高,我結合最近查詢到的資料,結合自己淺薄的見解,做出一點點介紹和綜述,希望可以幫到大家。如有不正,多請斧正!
1. Node.js到底是什么
Node.js在維基百科中就已經很明確的說明了,它是一個運行環境,并不是其他的什么比如軟件庫,簡而言之,和C#所需要的編譯環境一樣,Node.js就是JavaScript的編譯環境,它存在的目的就是為了讓JavaScript可以和其他的后端語言一樣能夠在瀏覽器上運行,換種說法就是,可以讓前端語言JavaScript在寫完之后交給Node.js進行編譯和解釋,它的存在對于JavaScript有了質的飛躍,對于一個前端來說利用JavaScript就可以編譯后臺代碼是一件多么爽飛天的事情。
簡單的Node.js命令就是
#node hello.js
2. V8引擎
我們都知道計算機處理器智能識別機器語言,而JavaScript是一門高級語言,計算機并不能直接讀懂。所以我們需要所謂的引擎來將其轉化成計算機所能理解的語言。v8引擎是由Google推出的,為其瀏覽器Chrome所設計的開源JavaScript引擎。得益于JIT,編譯模式的改變與編譯階段的優化,JavaScript的性能得到了一個飛躍。其源代碼是用c++寫的,感除了對JavaScript性能的大幅提升,v8引擎也提供了“嵌入”的功能,使得開發者也可以在自己的c++程序中使用“嵌入”的v8引擎,從而高效地編譯JavaScript,并加入c++的feature。要知道,作為一個底層得多的語言,c++可以實現的feature可要比JavaScript多得多。舉例說明,JavaScript本身并沒有read這么一個function。然而通過v8,我們可以將其綁定到一個用c++寫的read callback上,從而通過JavaScript我們也可以直接加載文件了。
于是,借助于v8種種便利的功能,Node.js誕生了。
3. 數據的請求和處理(表述的不太準確望海涵)
首先我們要注意的是瀏覽器給網站發請求的過程一直沒怎么變過。當瀏覽器給網站發了請求。服務器收到了請求,然后開始搜尋被請求的資源。如果有需要,服務器還會查詢一下數據庫,最后把響應結果傳回瀏覽器。不過,在傳統的web服務器中,每一個請求都會讓服務器創建一個新的進程來處理這個請求。后來有了Ajax,我們就不用每次都請求一個完整的新頁面了,取而代之的是,每次只請求需要的部分頁面信息就可以了。這顯然是一個進步。但是比如你要建一個類似微博的社交網站,導致的結果是你的好友會隨時的推送新的狀態,然后你的新鮮事會實時自動刷新。要達成這個需求,我們需要讓用戶一直與服務器保持一個有效連接。目前最簡單的實現方法,就是讓用戶和服務器之間保持長輪訓(long polling)。
HTTP請求不是持續的連接,你請求一次,服務器響應一次,然后就完了。長輪訓是一種利用HTTP模擬持續連接的技巧。具體來說,只要頁面載入了,不管你需不需要服務器給你響應信息,你都會給服務器發一個Ajax請求。這個請求不同于一般的Ajax請求,服務器不會直接給你返回信息,而是它要等著,直到服務器覺得該給你發信息了,它才會響應。比如,你的好友發了一條新鮮事,服務器就會把這個新鮮事當做響應發給你的瀏覽器,然后你的瀏覽器就刷新頁面了。瀏覽器收到響應刷新完之后,再發送一條新的請求給服務器,這個請求依然不會立即被響應。于是就開始重復以上步驟。利用這個方法,可以讓瀏覽器始終保持等待響應的狀態。雖然以上過程依然只有非持續的HTTP參與,但是我們模擬出了一個看似持續的連接狀態我們再看傳統的服務器。每次一個新用戶連到你的網站上,你的服務器就得開一個連接。每個連接都需要占一個進程,這些進程大部分時間都是閑著的(比如等著你好友發新鮮事,等好友發完才給用戶響應信息?;蛘叩戎鴶祿旆祷夭樵兘Y果什么的)。雖然這些進程閑著,但是照樣占用內存。這意味著,如果用戶連接數的增長到一定規模,你服務器沒準就要耗光內存直接癱了。這種情況怎么解決?解決方法就是剛才上邊說的:非阻塞和事件驅動。這些概念在我們談的這個情景里面其實沒那么難理解。你把非阻塞的服務器想象成一個loop循環,這個loop會一直跑下去。一個新請求來了,這個loop就接了這個請求,把這個請求傳給其他的進程(比如傳給一個搞數據庫查詢的進程),然后響應一個回調(callback)。完事了這loop就接著跑,接其他的請求。這樣下來。服務器就不會像之前那樣傻等著數據庫返回結果了。如果數據庫把結果返回來了,loop就把結果傳回用戶的瀏覽器,接著繼續跑。在這種方式下,你的服務器的進程就不會閑著等著。從而在理論上說,同一時刻的數據庫查詢數量,以及用戶的請求數量就沒有限制了。服務器只在用戶那邊有事件發生的時候才響應,這就是事件驅動。FriendFeed是用基于Python的非阻塞框架Tornado (知乎也用了這個框架) 來實現上面說的新鮮事功能的。不過,Node.js就比前者更妙了。Node.js的應用是通過javascript開發的,然后直接在Google的變態V8引擎上跑。
用了Node.js,你就不用擔心用戶端的請求會在服務器里跑了一段能夠造成阻塞的代碼了。因為javascript本身就是事件驅動的腳本語言。你回想一下,在給前端寫javascript的時候,更多時候你都是在搞事件處理和回調函數。所以javascript本身就是給事件處理量身定制的語言。
4. 使用Node.js的優劣(很重要)
在使用Node.js的時候我們可以知道,Node.js解決了很多JavaScript的痛點。當然Node.js作為一個語言也有很多都缺陷。
優勢
- 采用事件驅動、異步編程,為網絡服務而設計。其實Javascript的匿名函數和閉包特性非常適合事件驅動、異步編程。而且JavaScript也簡單易學,很多前端設計人員可以很快上手做后端設計。
- Node.js非阻塞模式的IO處理給Node.js帶來在相對低系統資源耗用下的高性能與出眾的負載能力,非常適合用作依賴其它IO資源的中間層服務。
- Node.js輕量高效,可以認為是數據密集型分布式部署環境下的實時應用系統的完美解決方案。Node非常適合如下情況:在響應客戶端之前,您預計可能有很高的流量,但所需的服務器端邏輯和處理不一定很多。
缺點
可靠性低。
單進程,單線程,只支持單核CPU,不能充分的利用多核CPU服務器。一旦這個進程崩掉,那么整個web服務就崩掉了。
當然對于這些缺點也喲普很多解決辦法:
- 開啟多個進程,每個進程綁定不同的端口,用反向代理服務器如 Nginx 做負載均衡,好處是我們可以借助強大的 Nginx 做一些過濾檢查之類的操作,同時能夠實現比較好的均衡策略,但壞處也是顯而易見——我們引入了一個間接層。
- 多進程綁定在同一個端口偵聽。在Node.js中,提供了進程間發送“文件句柄” 的功能。
- 一個進程負責監聽、接收連接,然后把接收到的連接平均發送到子進程中去處理。
5. 適用場景
SON APIs——構建一個Rest/JSON API服務,Node.js可以充分發揮其非阻塞IO模型以及JavaScript對JSON的功能支持(如JSON.stringfy函數)單頁面、多Ajax請求應用——如Gmail,前端有大量的異步請求,需要服務后端有極高的響應速度基于Node.js開發Unix命令行工具——Node.js可以大量生產子進程,并以流的方式輸出,這使得它非常適合做Unix命令行工具流式數據——傳統的Web應用,通常會將HTTP請求和響應看成是原子事件。而Node.js會充分利用流式數據這個特點,構建非常酷的應用。如實時文件上傳系統transloadit準實時應用系統——如聊天系統、微博系統,但Javascript是有垃圾回收機制的,這就意味著,系統的響應時間是不平滑的(GC垃圾回收會導致系統這一時刻停止工作)。如果想要構建硬實時應用系統,Erlang是個不錯的選擇。
結語
Node.js是一個對于前端工作者不可或缺的工具。尤其是對于JavaScript有著巨大的提升,現階段Node.js的應用已經有了非常蓬勃的發展。對于Node.js的學習和熟練運用,必不可少!以上。