第一次更新 查漏補缺昨晚零時寫的 辣雞輸入法導致錯別字太多瘪贱。
Node.js的到底是用來做什么的
在闡述之前我想放一個鏈接,這是國外的一個大神牙言,對于node.js非常好的一篇介紹的文章,英文比較好的朋友可以直接去閱讀酸钦,本文也很大程度上參考了這篇文章,也同時感謝知乎用戶廠長對于本文的翻譯咱枉!原文題目為Node.js is the New Black
Node.js的簡介
根據維基百科對于Node.js的介紹卑硫,我們可以知道一些基本關于Node.js的情況。Node.js是瑞安·達爾(Ryan Dahl)在2009年發(fā)明出來的一種一個能夠在服務器端運行JavaScript蚕断,并且可以開放源代碼欢伏,以及跨平臺運行JavaScript的一種運行環(huán)境。
Node.js采用了Google公司的V8引擎亿乳。Node.js允許通過JavaScript和一系列模塊來編寫服務器端應用和網絡相關的應用硝拧。核心模塊包括文件系統(tǒng)I/O、網絡(HTTP葛假、TCP障陶、UDP、DNS聊训、TLS/SSL等)咸这、二進制數據流、加密算法魔眨、數據流等等。Node模塊的API形式簡單酿雪,降低了編程的復雜度遏暴。
Node.js主要用于編寫像Web服務器一樣的網絡應用,這和PHP和Python是類似的指黎。但是Node.js與其他語言最大的不同之處在于朋凉,PHP等語言是阻塞的(只有前一條命令執(zhí)行完畢才會執(zhí)行后面的命令),而Node.js是非阻塞的(多條命令可以同時被運行醋安,通過回調函數得知命令已結束運行)杂彭。
Node.js是事件驅動的。開發(fā)者可以在不使用線程的情況下開發(fā)出一個能夠承載高并發(fā)的服務器吓揪。其他服務器端語言難以開發(fā)高并發(fā)應用亲怠,而且即使開發(fā)出來,性能也不盡人意柠辞。Node.js正是在這個前提下被創(chuàng)造出來团秽。Node.js把JavaScript的易學易用和Unix網絡編程的強大結合到了一起。
Node.js使用Google V8 JavaScript 引擎,因為
- V8是基于BSD許可證的開源軟件
- V8速度非诚扒冢快
- V8專注于網絡功能踪栋,在HTTP、DNS图毕、TCP等方面更加成熟
Node.js已經有數十萬模塊夷都,它們可以通過一個名為npm的管理器免費下載。Node.js開發(fā)社區(qū)主要有兩個郵件列表予颤、一個在freenode的名為#node.js的IRC頻道囤官。社區(qū)集中在NodeConf。
雜敘
在學習Web前端的朋友看來荣瑟,Node.js是一個經常會聽到而且無法回避的問題治拿,然而國內的資料相對較少,國外的資料大多數是以英文為主要藍本闡述的笆焰,所以友好度并不高劫谅,我結合最近查詢到的資料,結合自己淺薄的見解嚷掠,做出一點點介紹和綜述捏检,希望可以幫到大家。如有不正不皆,多請斧正贯城!
1. Node.js到底是什么
Node.js在維基百科中就已經很明確的說明了,它是一個運行環(huán)境霹娄,并不是其他的什么比如軟件庫能犯,簡而言之,和C#所需要的編譯環(huán)境一樣犬耻,Node.js就是JavaScript的編譯環(huán)境踩晶,它存在的目的就是為了讓JavaScript可以和其他的后端語言一樣能夠在瀏覽器上運行,換種說法就是枕磁,可以讓前端語言JavaScript在寫完之后交給Node.js進行編譯和解釋渡蜻,它的存在對于JavaScript有了質的飛躍,對于一個前端來說利用JavaScript就可以編譯后臺代碼是一件多么爽飛天的事情计济。
簡單的Node.js命令就是
#node hello.js
2. V8引擎
我們都知道計算機處理器智能識別機器語言茸苇,而JavaScript是一門高級語言,計算機并不能直接讀懂沦寂。所以我們需要所謂的引擎來將其轉化成計算機所能理解的語言学密。v8引擎是由Google推出的,為其瀏覽器Chrome所設計的開源JavaScript引擎传藏。得益于JIT则果,編譯模式的改變與編譯階段的優(yōu)化幔翰,JavaScript的性能得到了一個飛躍。其源代碼是用c++寫的西壮,感除了對JavaScript性能的大幅提升遗增,v8引擎也提供了“嵌入”的功能,使得開發(fā)者也可以在自己的c++程序中使用“嵌入”的v8引擎款青,從而高效地編譯JavaScript做修,并加入c++的feature。要知道抡草,作為一個底層得多的語言饰及,c++可以實現的feature可要比JavaScript多得多。舉例說明康震,JavaScript本身并沒有read這么一個function燎含。然而通過v8,我們可以將其綁定到一個用c++寫的read callback上腿短,從而通過JavaScript我們也可以直接加載文件了屏箍。
于是,借助于v8種種便利的功能橘忱,Node.js誕生了赴魁。
3. 數據的請求和處理(表述的不太準確望海涵)
首先我們要注意的是瀏覽器給網站發(fā)請求的過程一直沒怎么變過。當瀏覽器給網站發(fā)了請求钝诚。服務器收到了請求颖御,然后開始搜尋被請求的資源。如果有需要凝颇,服務器還會查詢一下數據庫潘拱,最后把響應結果傳回瀏覽器。不過拧略,在傳統(tǒng)的web服務器中泽铛,每一個請求都會讓服務器創(chuàng)建一個新的進程來處理這個請求。后來有了Ajax辑鲤,我們就不用每次都請求一個完整的新頁面了,取而代之的是杠茬,每次只請求需要的部分頁面信息就可以了月褥。這顯然是一個進步。但是比如你要建一個類似微博的社交網站瓢喉,導致的結果是你的好友會隨時的推送新的狀態(tài)宁赤,然后你的新鮮事會實時自動刷新。要達成這個需求栓票,我們需要讓用戶一直與服務器保持一個有效連接决左。目前最簡單的實現方法愕够,就是讓用戶和服務器之間保持長輪訓(long polling)。
HTTP請求不是持續(xù)的連接佛猛,你請求一次惑芭,服務器響應一次,然后就完了继找。長輪訓是一種利用HTTP模擬持續(xù)連接的技巧遂跟。具體來說,只要頁面載入了婴渡,不管你需不需要服務器給你響應信息幻锁,你都會給服務器發(fā)一個Ajax請求。這個請求不同于一般的Ajax請求边臼,服務器不會直接給你返回信息哄尔,而是它要等著,直到服務器覺得該給你發(fā)信息了柠并,它才會響應岭接。比如,你的好友發(fā)了一條新鮮事堂鲤,服務器就會把這個新鮮事當做響應發(fā)給你的瀏覽器亿傅,然后你的瀏覽器就刷新頁面了。瀏覽器收到響應刷新完之后瘟栖,再發(fā)送一條新的請求給服務器葵擎,這個請求依然不會立即被響應。于是就開始重復以上步驟半哟。利用這個方法酬滤,可以讓瀏覽器始終保持等待響應的狀態(tài)。雖然以上過程依然只有非持續(xù)的HTTP參與寓涨,但是我們模擬出了一個看似持續(xù)的連接狀態(tài)我們再看傳統(tǒng)的服務器盯串。每次一個新用戶連到你的網站上,你的服務器就得開一個連接戒良。每個連接都需要占一個進程体捏,這些進程大部分時間都是閑著的(比如等著你好友發(fā)新鮮事,等好友發(fā)完才給用戶響應信息糯崎〖哥裕或者等著數據庫返回查詢結果什么的)。雖然這些進程閑著沃呢,但是照樣占用內存年栓。這意味著,如果用戶連接數的增長到一定規(guī)模薄霜,你服務器沒準就要耗光內存直接癱了某抓。這種情況怎么解決纸兔?解決方法就是剛才上邊說的:非阻塞和事件驅動。這些概念在我們談的這個情景里面其實沒那么難理解否副。你把非阻塞的服務器想象成一個loop循環(huán)汉矿,這個loop會一直跑下去。一個新請求來了副编,這個loop就接了這個請求负甸,把這個請求傳給其他的進程(比如傳給一個搞數據庫查詢的進程),然后響應一個回調(callback)痹届。完事了這loop就接著跑呻待,接其他的請求。這樣下來队腐。服務器就不會像之前那樣傻等著數據庫返回結果了蚕捉。如果數據庫把結果返回來了,loop就把結果傳回用戶的瀏覽器柴淘,接著繼續(xù)跑迫淹。在這種方式下,你的服務器的進程就不會閑著等著为严。從而在理論上說敛熬,同一時刻的數據庫查詢數量,以及用戶的請求數量就沒有限制了第股。服務器只在用戶那邊有事件發(fā)生的時候才響應应民,這就是事件驅動。FriendFeed是用基于Python的非阻塞框架Tornado (知乎也用了這個框架) 來實現上面說的新鮮事功能的夕吻。不過诲锹,Node.js就比前者更妙了。Node.js的應用是通過javascript開發(fā)的涉馅,然后直接在Google的變態(tài)V8引擎上跑归园。
用了Node.js,你就不用擔心用戶端的請求會在服務器里跑了一段能夠造成阻塞的代碼了稚矿。因為javascript本身就是事件驅動的腳本語言庸诱。你回想一下,在給前端寫javascript的時候晤揣,更多時候你都是在搞事件處理和回調函數桥爽。所以javascript本身就是給事件處理量身定制的語言。
4. 使用Node.js的優(yōu)劣(很重要)
在使用Node.js的時候我們可以知道碉渡,Node.js解決了很多JavaScript的痛點。當然Node.js作為一個語言也有很多都缺陷母剥。
優(yōu)勢
- 采用事件驅動滞诺、異步編程形导,為網絡服務而設計。其實Javascript的匿名函數和閉包特性非常適合事件驅動习霹、異步編程朵耕。而且JavaScript也簡單易學,很多前端設計人員可以很快上手做后端設計淋叶。
- Node.js非阻塞模式的IO處理給Node.js帶來在相對低系統(tǒng)資源耗用下的高性能與出眾的負載能力阎曹,非常適合用作依賴其它IO資源的中間層服務。
- Node.js輕量高效煞檩,可以認為是數據密集型分布式部署環(huán)境下的實時應用系統(tǒng)的完美解決方案处嫌。Node非常適合如下情況:在響應客戶端之前,您預計可能有很高的流量斟湃,但所需的服務器端邏輯和處理不一定很多熏迹。
缺點
可靠性低。
單進程凝赛,單線程注暗,只支持單核CPU,不能充分的利用多核CPU服務器墓猎。一旦這個進程崩掉捆昏,那么整個web服務就崩掉了。
當然對于這些缺點也喲普很多解決辦法:
- 開啟多個進程毙沾,每個進程綁定不同的端口骗卜,用反向代理服務器如 Nginx 做負載均衡,好處是我們可以借助強大的 Nginx 做一些過濾檢查之類的操作搀军,同時能夠實現比較好的均衡策略膨俐,但壞處也是顯而易見——我們引入了一個間接層。
- 多進程綁定在同一個端口偵聽罩句。在Node.js中焚刺,提供了進程間發(fā)送“文件句柄” 的功能。
- 一個進程負責監(jiān)聽门烂、接收連接乳愉,然后把接收到的連接平均發(fā)送到子進程中去處理。
5. 適用場景
SON APIs——構建一個Rest/JSON API服務屯远,Node.js可以充分發(fā)揮其非阻塞IO模型以及JavaScript對JSON的功能支持(如JSON.stringfy函數)單頁面蔓姚、多Ajax請求應用——如Gmail,前端有大量的異步請求慨丐,需要服務后端有極高的響應速度基于Node.js開發(fā)Unix命令行工具——Node.js可以大量生產子進程坡脐,并以流的方式輸出,這使得它非常適合做Unix命令行工具流式數據——傳統(tǒng)的Web應用房揭,通常會將HTTP請求和響應看成是原子事件备闲。而Node.js會充分利用流式數據這個特點晌端,構建非常酷的應用恬砂。如實時文件上傳系統(tǒng)transloadit準實時應用系統(tǒng)——如聊天系統(tǒng)咧纠、微博系統(tǒng),但Javascript是有垃圾回收機制的泻骤,這就意味著漆羔,系統(tǒng)的響應時間是不平滑的(GC垃圾回收會導致系統(tǒng)這一時刻停止工作)。如果想要構建硬實時應用系統(tǒng)狱掂,Erlang是個不錯的選擇演痒。
結語
Node.js是一個對于前端工作者不可或缺的工具。尤其是對于JavaScript有著巨大的提升符欠,現階段Node.js的應用已經有了非常蓬勃的發(fā)展嫡霞。對于Node.js的學習和熟練運用,必不可少希柿!以上诊沪。