專注全棧大前端,愛前端整理了一批2019年最新WEB前端教學視頻旨枯,不論是零基礎想要學習前端還是學完在工作想要提升自己蹬昌,這些資料都會給你帶來幫助,從HTML到各種框架攀隔,幫助所有想要學好前端的同學皂贩,學習規(guī)劃、學習路線昆汹、學習資料明刷、問題解答。只要加入全棧大前端學習交流Q群:137503198满粗,即可免費獲取辈末。
介紹
JavaScript的日益普及帶來了很多變化,而今天的Web開發(fā)面貌卻截然不同。我們現(xiàn)在可以在服務器上運行JavaScript以及在瀏覽器中執(zhí)行的操作幾年前很難想象挤聘,或者封裝在沙盒環(huán)境中轰枝,如Flash或Java Applet。
在深入研究Node.js之前组去,您可能希望了解在堆棧中使用JavaScript的好處狸膏,它統(tǒng)一了語言和數(shù)據(jù)格式(JSON),允許您以最佳方式重用開發(fā)人員資源添怔。由于這比JavaScript特別是Node.js更有益,我們在此不再討論它贤旷。但是將Node合并到堆棧中是一個關鍵優(yōu)勢广料。
正如維基百科所說:“Node.js是Google的V8 JavaScript引擎,libuv平臺抽象層和核心庫的打包匯編幼驶,它本身主要用JavaScript編寫艾杏。”除此之外尔许,值得注意的是Ryan Dahl慕爬,創(chuàng)作者Node.js的目標是創(chuàng)建具有推送功能的實時網(wǎng)站扑庞,“受Gmail等應用程序的啟發(fā)”。在Node.js中勃蜘,他為開發(fā)人員提供了一個工具,用于處理非阻塞假残,事件驅(qū)動的I / O范例缭贡。
在基于無狀態(tài)請求 - 響應范例的20多年無狀態(tài)網(wǎng)絡之后,我們終于擁有了具有實時雙向連接的Web應用程序辉懒。
用一句話來說:Node.js在基于websockets的推送技術(shù)的實時Web應用程序中大放異彩阳惹。那是什么革命性的?好吧眶俩,在基于無狀態(tài)請求 - 響應范例的20多年無狀態(tài)網(wǎng)絡之后莹汤,我們終于擁有了具有實時雙向連接的Web應用程序,其中客戶端和服務器都可以啟動通信颠印,允許它們自由地交換數(shù)據(jù)纲岭。這與典型的Web響應范例形成鮮明對比,客戶端總是發(fā)起通信嗽仪。此外荒勇,它都基于在標準端口80上運行的開放Web堆棧(HTML,CSS和JS)闻坚。
有人可能會爭辯說沽翔,我們多年來一直以Flash和Java Applet的形式擁有這一點 - 但實際上,這些只是使用Web作為傳輸協(xié)議傳遞給客戶端的沙盒環(huán)境。此外仅偎,它們是隔離運行的跨蟹,通常在非標準端口上運行,這可能需要額外的權(quán)限等橘沥。
憑借其所有優(yōu)勢窗轩,Node.js現(xiàn)在在依賴其獨特優(yōu)勢的眾多知名公司的技術(shù)堆棧中發(fā)揮著關鍵作用。Node.js基金會已經(jīng)整合了所有關于為什么企業(yè)應該在Node.js基金會的案例研究頁面上找到的簡短演示中考慮Node.js的最佳思考座咆。
在這個Node.js指南中痢艺,我將不僅討論如何實現(xiàn)這些優(yōu)勢,而且還討論為什么你可能想要使用Node.js - 以及為什么不 - 使用一些經(jīng)典的Web應用程序模型作為示例介陶。
它是如何工作的堤舒?
Node.js的主要思想是:在面向跨分布式設備運行的數(shù)據(jù)密集型實時應用程序時,使用非阻塞哺呜,事件驅(qū)動的I / O保持輕量級和高效舌缤。
那是滿口的。
它的真正含義是Node.js 不是一個將在Web開發(fā)領域占主導地位的銀彈新平臺某残。相反国撵,它是一個滿足特定需求的平臺。
它的真正含義是Node.js 不是一個將在Web開發(fā)領域占主導地位的銀彈新平臺玻墅。相反介牙,它是一個滿足特定需求的平臺。了解這一點絕對必要椭豫。您絕對不希望將Node.js用于CPU密集型操作; 實際上耻瑟,將它用于繁重的計算將幾乎消除其所有優(yōu)點。Node真正發(fā)揮作用的地方在于構(gòu)建快速赏酥,可擴展的網(wǎng)絡應用程序喳整,因為它能夠以高吞吐量處理大量同時連接,這相當于高可擴展性裸扶。
如何在引擎蓋下工作非常有趣框都。與傳統(tǒng)的Web服務技術(shù)相比,每個連接(請求)產(chǎn)生一個新線程呵晨,占用系統(tǒng)RAM并最終以可用的RAM量最大化魏保,Node.js在單線程上運行,使用非阻塞I / O調(diào)用摸屠,允許它支持事件循環(huán)中保存的數(shù)萬個并發(fā)連接谓罗。
快速計算:假設每個線程可能隨附2 MB內(nèi)存,在具有8 GB RAM的系統(tǒng)上運行使我們理論上最多可以有4,000個并發(fā)連接(計算來自Michael Abernethy的文章“Just what is Node” .js季二?“檩咱,2011年在IBM developerWorks上發(fā)布;遺憾的是揭措,這篇文章不再可用了),加上線程之間的上下文切換成本刻蚯。這就是您通常在傳統(tǒng)的網(wǎng)絡服務技術(shù)中處理的場景绊含。通過避免這一切,Node.js實現(xiàn)了超過1M并發(fā)連接的可伸縮性級別炊汹,以及超過600k并發(fā)的websockets連接躬充。
當然,存在在所有客戶端請求之間共享單個線程的問題讨便,這是編寫Node.js應用程序的潛在缺陷充甚。首先,繁重的計算可能會阻塞Node的單個線程并導致所有客戶端出現(xiàn)問題(稍后會詳細說明)霸褒,因為傳入的請求將被阻塞津坑,直到所述計算完成為止。其次傲霸,開發(fā)人員需要非常小心,不要讓異常冒泡到核心(最頂層)Node.js事件循環(huán)眉反,這將導致Node.js實例終止(有效地崩潰程序)昙啄。
用于避免冒泡到表面的異常的技術(shù)是將錯誤作為回調(diào)參數(shù)傳遞回調(diào)用者(而不是像在其他環(huán)境中那樣拋出它們)。即使一些未處理的異常設法冒泡寸五,也開發(fā)了一些工具來監(jiān)視Node.js進程并執(zhí)行崩潰實例的必要恢復(盡管您可能無法恢復用戶會話的當前狀態(tài))梳凛,最常見的是Forever模塊,或者使用不同的方法與外部系統(tǒng)工具upstart和monit梳杏,甚至只是暴發(fā)戶韧拒。
NPM:節(jié)點包管理器
在討論Node.js時,有一點絕對不應該被忽略的是內(nèi)置支持使用NPM進行包管理十性,NPM是默認情況下每個Node.js安裝的工具叛溢。NPM模塊的概念與Ruby Gems非常相似:一組公開可用的可重用組件,可通過在線存儲庫輕松安裝劲适,具有版本和依賴關系管理楷掉。
可以在npm網(wǎng)站上找到已打包模塊的完整列表,也可以使用自動與Node.js一起安裝的npm CLI工具進行訪問霞势。模塊生態(tài)系統(tǒng)對所有人開放烹植,任何人都可以發(fā)布自己的模塊,該模塊將列在npm存儲庫中愕贡。
今天一些最有用的npm模塊是:
表達 - Express.js-或簡單表達 - 一個受Sinatra啟發(fā)的Node.js Web開發(fā)框架草雕,以及當今大多數(shù)Node.js應用程序的事實標準。
hapi - 一個非常模塊化且易于使用的以配置為中心的框架固以,用于構(gòu)建Web和服務應用程序
connect - Connect是Node.js的可擴展HTTP服務器框架墩虹,提供了一系列稱為中間件的高性能“插件”; 作為Express的基礎。
socket.io和 sockjs - 今天兩個最常見的websockets組件的服務器端組件。
帕格(以前稱為Jade) - 受HAML啟發(fā)的流行模板引擎之一败晴,Express.js中的默認值浓冒。
mongodb和 mongojs - MongoDB包裝器,為Node.js中的MongoDB對象數(shù)據(jù)庫提供API尖坤。
redis - Redis客戶端庫稳懒。
lodash(下劃線,lazy.js) - JavaScript實用程序帶慢味。Underscore發(fā)起了游戲场梆,但被其兩個對手之一推翻,主要是因為更好的性能和模塊化實施纯路。
永遠 - 可能是確保給定節(jié)點腳本連續(xù)運行的最常用實用程序或油。在遇到任何意外故障時,將Node.js進程保持在生產(chǎn)狀態(tài)驰唬。
bluebird - 功能齊全的Promises / A +實現(xiàn)顶岸,性能非常出色
moment - 用于解析,驗證叫编,操作和格式化日期的JavaScript日期庫辖佣。
名單還在繼續(xù)。那里有很多真正有用的包搓逾,可供所有人使用(對于我在這里省略的那些沒有冒犯)卷谈。
應該使用Node.js的示例
CHAT
聊天是最典型的實時多用戶應用程序。從IRC(在當天)霞篡,通過在非標準端口上運行的許多專有和開放協(xié)議世蔗,到今天在Node.js中實現(xiàn)一切的能力,其中websockets在標準端口80上運行朗兵。
聊天應用程序?qū)嶋H上是Node.js的最佳示例:它是一個輕量級污淋,高流量,數(shù)據(jù)密集型(但低處理/計算)的應用程序余掖,可跨分布式設備運行芙沥。它也是一個很好的學習用例,因為它很簡單浊吏,但它涵蓋了你在典型的Node.js應用程序中使用的大部分范例而昨。
讓我們試著描繪它是如何工作的。
在最簡單的例子中找田,我們在我們的網(wǎng)站上有一個聊天室歌憨,人們可以通過一對多(實際上所有)方式交換消息。例如墩衙,假設網(wǎng)站上有三個人都連接到我們的留言板务嫡。
在服務器端甲抖,我們有一個簡單的Express.js應用程序,它實現(xiàn)了兩件事:
一個GET /請求處理程序心铃,它為包含消息板和“發(fā)送”按鈕的網(wǎng)頁提供服務准谚,以初始化新的消息輸入,以及
一個websockets服務器去扣,用于偵聽websocket客戶端發(fā)出的新消息柱衔。
在客戶端,我們有一個HTML頁面愉棱,其中設置了幾個處理程序唆铐,一個用于“發(fā)送”按鈕單擊事件,它接收輸入消息并將其發(fā)送到websocket奔滑,另一個用于偵聽新的傳入消息在websockets客戶端上(即艾岂,由服務器現(xiàn)在希望客戶端顯示的其他用戶發(fā)送的消息)。
當其中一個客戶發(fā)布消息時朋其,會發(fā)生以下情況:
瀏覽器通過JavaScript處理程序捕獲“發(fā)送”按鈕王浴,從輸入字段(即消息文本)中獲取值,并使用連接到我們服務器的websocket客戶端(在網(wǎng)頁初始化時初始化)發(fā)出websocket消息梅猿。
websocket連接的服務器端組件接收消息叼耙,并使用廣播方法將其轉(zhuǎn)發(fā)到所有其他連接的客戶端。
所有客戶端都通過在網(wǎng)頁中運行的websockets客戶端組件將新消息作為推送消息接收粒没。然后,他們通過將新消息附加到電路板來獲取消息內(nèi)容并就地更新網(wǎng)頁簇爆。
這是最簡單的例子癞松。對于更強大的解決方案,您可以使用基于Redis存儲的簡單緩存入蛆∠烊兀或者在更高級的解決方案中,消息隊列用于處理到客戶端的消息路由以及更強大的傳遞機制哨毁,其可以覆蓋臨時連接丟失或在注冊客戶端脫機時存儲消息枫甲。但無論您做出哪些改進,Node.js仍將按照相同的基本原則運行:對事件做出反應扼褪,處理許多并發(fā)連接想幻,并保持用戶體驗的流暢性。
對象數(shù)據(jù)庫頂部的API
雖然Node.js真的很適合實時應用程序话浇,但它非常適合從對象DB(例如MongoDB)公開數(shù)據(jù)脏毯。JSON存儲的數(shù)據(jù)允許Node.js在沒有阻抗不匹配和數(shù)據(jù)轉(zhuǎn)換的情況下運行。
例如幔崖,如果您正在使用Rails食店,那么您將從JSON轉(zhuǎn)換為二進制模型渣淤,然后在Backbone.js,Angular.js等使用數(shù)據(jù)時將它們作為JSON通過HTTP公開吉嫩,甚至是簡單的jQuery AJAX調(diào)用价认。使用Node.js,您可以使用REST API公開您的JSON對象自娩,供客戶端使用用踩。此外,在從數(shù)據(jù)庫讀取或?qū)懭霑r(如果您使用的是MongoDB)椒功,您無需擔心在JSON和其他任何內(nèi)容之間進行轉(zhuǎn)換捶箱。總之动漾,通過在客戶端丁屎,服務器和數(shù)據(jù)庫中使用統(tǒng)一的數(shù)據(jù)序列化格式,可以避免需要多次轉(zhuǎn)換旱眯。
排隊輸入
如果您收到大量并發(fā)數(shù)據(jù)晨川,您的數(shù)據(jù)庫可能會成為瓶頸。如上所述删豺,Node.js可以輕松地自己處理并發(fā)連接共虑。但是因為數(shù)據(jù)庫訪問是一種阻塞操作(在這種情況下),我們遇到了麻煩呀页。解決方案是在數(shù)據(jù)真正寫入數(shù)據(jù)庫之前確認客戶端的行為妈拌。
通過這種方法,系統(tǒng)可以在高負載下保持其響應性蓬蝶,這在客戶端不需要確認成功數(shù)據(jù)寫入時尤其有用尘分。典型的例子包括:記錄或?qū)懭胗脩舾檾?shù)據(jù),分批處理丸氛,直到以后才使用; 以及不需要立即反映的操作(例如更新Facebook上的“喜歡”計數(shù))培愁,其中最終的一致性(在NoSQL世界中經(jīng)常使用)是可以接受的。
數(shù)據(jù)通過某種緩存或消息排隊基礎結(jié)構(gòu)(如RabbitMQ或ZeroMQ)排隊缓窜,并通過單獨的數(shù)據(jù)庫批處理寫入過程或計算密集型處理后端服務進行消化定续,這些服務是在更好的平臺中編寫的,用于執(zhí)行此類任務禾锤。類似的行為可以用其他語言/框架實現(xiàn)私股,但不能在相同的硬件上實現(xiàn),具有相同的高維護吞吐量恩掷。
簡而言之:使用Node庇茫,您可以將數(shù)據(jù)庫寫入到一邊并稍后處理它們,就像它們成功一樣螃成。
數(shù)據(jù)流
在更傳統(tǒng)的Web平臺中旦签,HTTP請求和響應被視為孤立事件; 事實上查坪,他們實際上是溪流∧牛可以在Node.js中使用此觀察來構(gòu)建一些很酷的功能偿曙。例如,可以在文件仍在上傳時處理文件羔巢,因為數(shù)據(jù)通過流進入望忆,我們可以以在線方式處理它。這可以用于實時音頻或視頻編碼竿秆,以及不同數(shù)據(jù)源之間的代理(參見下一節(jié))启摄。
代理
Node.js很容易用作服務器端代理,它可以以非阻塞方式處理大量的同時連接幽钢。它對于使用不同響應時間代理不同服務或從多個源點收集數(shù)據(jù)特別有用歉备。
例如:考慮服務器端應用程序與第三方資源進行通信,從不同來源提取數(shù)據(jù)匪燕,或?qū)D像和視頻等資產(chǎn)存儲到第三方云服務蕾羊。
盡管存在專用代理服務器,但如果您的代理基礎架構(gòu)不存在或者您需要本地開發(fā)解決方案帽驯,則使用Node可能會有所幫助龟再。通過這個,我的意思是你可以構(gòu)建一個客戶端應用程序與Node.js開發(fā)服務器的資產(chǎn)和代理/存根API請求尼变,而在生產(chǎn)中你可以處理這種與專用代理服務(nginx利凑,HAProxy等)的交互)。
BROKERAGE - 股票交易者的儀表板
讓我們回到應用程序級別嫌术。桌面軟件占主導地位哀澈,但可以很容易地用實時網(wǎng)絡解決方案取代的另一個例子是經(jīng)紀人的交易軟件,用于跟蹤股票價格蛉威,執(zhí)行計算/技術(shù)分析,以及創(chuàng)建圖表/圖表走哺。
切換到基于Web的實時解決方案將允許經(jīng)紀人輕松切換工作站或工作場所蚯嫌。很快,我們可能會開始在佛羅里達州的海灘上看到它們......或者伊維薩島或巴厘島丙躏。
應用監(jiān)控儀表板
另一個常見的用例择示,其中Node-with-web-socket完全適合:跟蹤網(wǎng)站訪問者并實時可視化他們的交互。
您可以從用戶那里收集實時統(tǒng)計信息晒旅,甚至可以通過在訪問渠道中的特定點打開通信渠道時與訪問者進行有針對性的互動栅盲,將其移至更高級別。(如果你有興趣废恋,這個想法已經(jīng)被CANDDi產(chǎn)品化了谈秫。)
想象一下扒寄,如果您能夠?qū)崟r了解訪問者的行為,那么如何改善您的業(yè)務 - 如果您能夠想象他們的互動拟烫。使用Node.js的實時雙向套接字该编,現(xiàn)在就可以了。
系統(tǒng)監(jiān)控儀表板
現(xiàn)在硕淑,讓我們訪問基礎設施方面的事情课竣。例如,想象一下置媳,SaaS提供商希望為其用戶提供服務監(jiān)控頁面于樟,如GitHub的狀態(tài)頁面。通過Node.js事件循環(huán)拇囊,我們可以創(chuàng)建一個功能強大的基于Web的儀表板迂曲,以異步方式檢查服務的狀態(tài),并使用websockets將數(shù)據(jù)推送到客戶端寂拆。
內(nèi)部(公司內(nèi)部)和公共服務的狀態(tài)都可以使用該技術(shù)實時和實時報告奢米。進一步推動這一想法并嘗試設想電信運營商,云/網(wǎng)絡/托管提供商或某些金融機構(gòu)中的網(wǎng)絡運營中心(NOC)監(jiān)控應用程序纠永,所有這些應用程序都運行在由Node.js和websockets支持的開放Web堆棧上而不是Java和/或Java Applet鬓长。
注意:不要嘗試在Node中構(gòu)建硬實時系統(tǒng)(即需要一致響應時間的系統(tǒng))。Erlang可能是該類應用程序的更好選擇尝江。
可以使用Node.js的位置
服務器端Web應用程序
帶有Express.js的Node.js也可用于在服務器端創(chuàng)建經(jīng)典Web應用程序涉波。但是,雖然可能炭序,Node.js將攜帶呈現(xiàn)HTML的請求 - 響應范例不是最典型的用例啤覆。有人支持和反對這種方法。以下是一些需要考慮的事實:
優(yōu)點:
如果您的應用程序沒有任何CPU密集型計算惭聂,那么您可以使用Javascript存儲對象數(shù)據(jù)庫(如MongoDB)從上到下構(gòu)建它窗声,甚至可以在數(shù)據(jù)庫級別構(gòu)建它。這顯著簡化了發(fā)展(包括招聘)辜纲。
Crawlers收到一個完全呈現(xiàn)的HTML響應笨觅,這比單個頁面應用程序或在Node.js上運行的websockets應用程序更具SEO。
缺點:
任何CPU密集型計算都會阻止Node.js的響應耕腾,因此線程平臺是一種更好的方法见剩。或者扫俺,您可以嘗試擴展計算[*]苍苞。
將Node.js與關系數(shù)據(jù)庫一起使用仍然非常痛苦(更多細節(jié)見下文)。如果您正在嘗試執(zhí)行關系操作狼纬,請幫自己一個忙羹呵,并選擇Rails骂际,Django或ASP.Net MVC等任何其他環(huán)境。
[*]這些CPU密集型計算的替代方案是創(chuàng)建一個高度可擴展的MQ支持環(huán)境担巩,該環(huán)境具有后端處理功能方援,以使Node成為一個面向前端的“職員”,以異步方式處理客戶端請求涛癌。
不應該使用Node.js的地方
服務器端WEB應用程序W / A關系數(shù)據(jù)庫的背后
例如犯戏,將Node.js與Express.js與Ruby on Rails進行比較時,在訪問PostgreSQL拳话,MySQL和Microsoft SQL Server等關系數(shù)據(jù)庫時先匪,曾經(jīng)有過一個干凈的決策支持后者。
Node.js的關系數(shù)據(jù)庫工具仍處于早期階段弃衍。另一方面呀非,Rails自動提供開箱即用的數(shù)據(jù)訪問設置以及數(shù)據(jù)庫架構(gòu)遷移支持工具和其他Gems(雙關語)。Rails及其對等框架具有成熟且經(jīng)過驗證的Active Record或Data Mapper數(shù)據(jù)訪問層實現(xiàn)镜盯。[*]
但事情發(fā)生了變化岸裙。Sequelize,TypeORM和Bookshelf在成為成熟的ORM解決方案方面走了很長的路速缆。如果您希望從GraphQL查詢生成SQL降允,那么可能還需要查看Join Monster。
[*]使用Node作為前端艺糜,同時保持Rails后端并輕松訪問關系數(shù)據(jù)庫是可能的剧董,而且并不罕見。
相關: 后端:使用Gatsby.js和Node.js進行靜態(tài)站點更新
重型服務器端計算/處理
當涉及到繁重的計算時破停,Node.js并不是最好的平臺翅楼。不,你絕對不想在Node.js中構(gòu)建一個Fibonacci計算服務器真慢。通常毅臊,任何CPU密集型操作都會消除Node提供的所有吞吐量優(yōu)勢及其事件驅(qū)動的非阻塞I / O模型,因為任何傳入的請求都會在線程被數(shù)字運算占用時被阻止 - 假設您正在嘗試在您響應請求的同一個Node實例中運行計算黑界。
如前所述管嬉,Node.js是單線程的,只使用一個CPU核心园爷。在多核服務器上添加并發(fā)性時宠蚂,Node核心團隊正在以集群模塊的形式完成一些工作[ref:http://nodejs.org/api/cluster.html]式撼。您還可以通過nginx在反向代理后面很容易地運行幾個Node.js服務器實例童社。
使用群集,您仍然應該將所有繁重的計算卸載到在更合適的環(huán)境中編寫的后臺進程著隆,并讓它們通過像RabbitMQ這樣的消息隊列服務器進行通信扰楼。
即使您的后臺處理最初可能在同一服務器上運行呀癣,這種方法也有可能實現(xiàn)非常高的可伸縮性。這些后臺處理服務可以輕松地分發(fā)到單獨的工作服務器弦赖,而無需配置前置Web服務器的負載项栏。
當然,您也可以在其他平臺上使用相同的方法蹬竖,但是使用Node.js沼沈,您可以獲得我們所討論的高reqs / sec吞吐量,因為每個請求都是一個非潮也蓿快速有效的小任務列另。
結(jié)論
我們討論了Node.js從理論到實踐,從它的目標和抱負開始旦装,并以其最佳點和陷阱結(jié)束页衙。當人們遇到Node的問題時,它幾乎總是歸結(jié)為阻塞操作是所有邪惡的根源 --99%的Node濫用是直接后果阴绢。
在Node中店乐,阻塞操作是所有邪惡的根源 - 99%的Node濫用是直接后果。
請記咨胂:從未創(chuàng)建過Node.js來解決計算擴展問題眨八。它的創(chuàng)建是為了解決I / O擴展問題,它確實很好棒妨。
為什么要使用Node.js踪古?如果您的用例不包含CPU密集型操作,也不訪問任何阻塞資源券腔,您可以利用Node.js的優(yōu)勢伏穆,享受快速,可擴展的網(wǎng)絡應用程序纷纫。歡迎來到實時網(wǎng)站枕扫。
專注全棧大前端,愛前端整理了一批2019年最新WEB前端教學視頻辱魁,不論是零基礎想要學習前端還是學完在工作想要提升自己烟瞧,這些資料都會給你帶來幫助,從HTML到各種框架染簇,幫助所有想要學好前端的同學参滴,學習規(guī)劃、學習路線锻弓、學習資料砾赔、問題解答。只要加入全棧大前端學習交流Q群:137503198,即可免費獲取暴心。