當(dāng)我們學(xué)習(xí)一項(xiàng)新的事物的時(shí)候,我們首先要知道它來自哪里忍啤?它是什么加勤?能做什么或者換句話說,能解決什么問題同波?沒有一樣?xùn)|西是最好的鳄梅,是可以替代所有的,但在某一領(lǐng)域它是最適合的未檩,正如 Node.js 它可能是某些程序員苦苦追尋的東西戴尸,也可能是某些程序員不會(huì)去關(guān)心的東西。本文主要為您介紹 Node.js 的背景及它能做什么冤狡,擅長什么孙蒙,不會(huì)涉及到復(fù)雜的代碼層面的知識(shí)講解项棠,如果你覺得自己很熟悉了,也可以忽略它挎峦。
作者簡介:五月君香追,Nodejs Developer,熱愛技術(shù)坦胶、喜歡分享的 90 后青年翅阵,公眾號(hào)「Nodejs技術(shù)棧」迁央,Github 開源項(xiàng)目 https://www.nodejs.red
文末附上筆者最近整理的 Node.js 技術(shù)棧學(xué)習(xí)指南路線圖 供大家學(xué)習(xí)參考!
背景介紹
Node.js? is a JavaScript runtime built on Chrome's V8 JavaScript engine. 這是來自 Node.js 官網(wǎng) https://nodejs.org/en/ 的一段介紹滥崩,翻譯成中文意為 Node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境岖圈。這里重點(diǎn)幾個(gè)關(guān)鍵詞 V8、JavaScript 后續(xù)會(huì)講解钙皮,從這里可以看出 Node.js 并不是一門新的編程語言蜂科,做為初學(xué)者這點(diǎn)先要弄清楚,它是 JavaScript 的運(yùn)行環(huán)境短条,更進(jìn)一步的說是在服務(wù)端的運(yùn)行環(huán)境导匣,因此這里的編程語言指的是 JavaScript。
時(shí)間回歸到 2009 年茸时,在當(dāng)時(shí) JavaScript 還是一個(gè)跑在瀏覽器環(huán)境里的一門腳本語言贡定,當(dāng)時(shí)的筆者還是一名高中生,接觸的編程語言是 VB 并不知 JavaScript 為何物可都,但隨后接觸 JavaScript 之后了解到這之前用它可以寫一些瀏覽器腳本缓待,做一些動(dòng)態(tài)特效,主要用于前端頁面交互渠牲。在 2009 這一時(shí)間線之后 Javascript 不只運(yùn)行于瀏覽器旋炒,還可以運(yùn)行于服務(wù)端,簡直打通了前端與后端的任督二脈签杈,當(dāng)然這要?dú)w功于 Node.js 之父 Ryan Dahl瘫镇。一度認(rèn)為這是很偉大的,在眾多編程語言里答姥,為什么會(huì)選擇 JavaScript 呢铣除?且看下面介紹。
為什么是 JavaScript踢涌?
Node.js 使用了一個(gè)事件驅(qū)動(dòng)通孽、非阻塞式 I/O 的模型,使其輕量又高效睁壁。這是來自于 Node.js 的另一個(gè)介紹背苦,關(guān)鍵詞 事件驅(qū)動(dòng)互捌、非阻塞式 I/O 因此,在基于這些條件之下 Node.js 作者 Ryan Dahl 在評估了 C行剂、Lua秕噪、Haskell、Ruby厚宰、JavaScript 等語言之后腌巾,最終選擇了 JavaScript,為什么呢铲觉?
JavaScript 是一個(gè)單線程的語言澈蝙,單線程的優(yōu)點(diǎn)是不會(huì)像 Java 這些多線程語言在編程時(shí)出現(xiàn)線程同步、線程鎖問題同時(shí)也避免了上下文切換帶來的性能開銷問題撵幽,那么其實(shí)在瀏覽器環(huán)境也只能是單線程灯荧,可以想象一下多線程對同一個(gè) DOM 進(jìn)行操作是什么場景?不是亂套了嗎盐杂?那么單線程可能你會(huì)想到的一個(gè)問題是逗载,前面一個(gè)執(zhí)行不完,后面不就卡住了嗎链烈?當(dāng)然不能這樣子的厉斟,JavaScript 是一種采用了事件驅(qū)動(dòng)、異步回調(diào)的模式强衡,另外 JavaScript 在服務(wù)端不存在什么歷史包袱擦秽,在虛擬機(jī)上由于又有了 Chrome V8 的支持,使得 JavaScript 成為了 Node.js 的首選語言食侮。
為什么選擇 JavaScript 作者 Ryan Dahl 應(yīng)該是最有發(fā)言權(quán)的号涯,這里查了一些資料及參考了 深入淺出 Node.js 一書,供大家有個(gè)初步的認(rèn)知锯七。
Node.js 架構(gòu)
Node.js 由 Libuv链快、Chrome V8、一些核心 API 構(gòu)成眉尸,如下圖所示:
以上展示了 Node.js 的構(gòu)成域蜗,下面做下簡單說明:
- Node Standard Library:Node.js 標(biāo)準(zhǔn)庫,對外提供的 JavaScript 接口噪猾,例如模塊 http霉祸、buffer、fs袱蜡、stream 等
- Node bindings:這里就是 JavaScript 與 C++ 連接的橋梁丝蹭,對下層模塊進(jìn)行封裝,向上層提供基礎(chǔ)的 API 接口坪蚁。
- V8:Google 開源的高性能 JavaScript 引擎奔穿,使用 C++ 開發(fā)镜沽,并且應(yīng)用于谷歌瀏覽器。如果您感興趣想學(xué)習(xí)更多的 V8 引擎知識(shí)贱田,請?jiān)L問 What is V8?
- Libuv:是一個(gè)跨平臺(tái)的支持事件驅(qū)動(dòng)的 I/O 庫缅茉。它是使用 C 和 C++ 語言為 Node.js 所開發(fā)的,同時(shí)也是 I/O 操作的核心部分男摧,例如讀取文件和 OS 交互蔬墩。來自一份 Libuv 的中文教程
- C-ares:C-ares 是一個(gè)異步 DNS 解析庫
- Low-Level Components:提供了 http 解析、OpenSSL耗拓、數(shù)據(jù)壓縮(zlib)等功能拇颅。
以上只是做一個(gè)初步的認(rèn)知,如果你想深入了解 Node.js 那么多每個(gè)點(diǎn)都是值得你深入研究的乔询。
來自 stack overflow 的一個(gè)參考:which-is-correct-node-js-architecture
Node.js 特點(diǎn)
在了解了 Node.js 的一些背景及架構(gòu)模型之后蔬蕊,已經(jīng)解決了它來自哪里?是什么哥谷?這個(gè)問題,現(xiàn)在我們來看看能解決什么問題麻献?它適合做什么们妥?
在這之前不知道您有沒有聽說過,Node.js 很擅長 I/O 密集型任務(wù)勉吻,應(yīng)對一些 I/O 密集型的高并發(fā)場景還是很有優(yōu)勢的监婶,事實(shí)也如此,這也是它的定位:提供一種簡單安全的方法在 JavaScript 中構(gòu)建高性能和可擴(kuò)展的網(wǎng)絡(luò)應(yīng)用程序齿桃。
- 單線程
Node.js 使用單線程來運(yùn)行惑惶,而不是向 Apache HTTP 之類的其它服務(wù)器,每個(gè)請求將生產(chǎn)一個(gè)線程短纵,這種方法避免了 CPU 上下文切換和內(nèi)存中的大量執(zhí)行堆棧带污,這也是 Nginx 和其它服務(wù)器為解決 “上一個(gè) 10 年,著名的 C10K 并發(fā)連接問題” 而采用的方法香到。
- 非阻塞 I/O
Node.js 避免了由于需要等待輸入或者輸出(數(shù)據(jù)庫鱼冀、文件系統(tǒng)、Web服務(wù)器...)響應(yīng)而造成的 CPU 時(shí)間損失悠就,這得益于 Libuv 強(qiáng)大的異步 I/O千绪。
- 事件驅(qū)動(dòng)編程
事件與回調(diào)在 JavaScript 中已是屢見不鮮,同時(shí)這種編程對于習(xí)慣同步思路的同學(xué)來說可能一時(shí)很難理解梗脾,但是這種編程模式荸型,確是一種高性能的服務(wù)模型。Node.js 與 Nginx 均是基于事件驅(qū)動(dòng)的方式實(shí)現(xiàn)炸茧,不同之處在于 Nginx 采用純 C 進(jìn)行編寫瑞妇,僅適用于 Web 服務(wù)器稿静,在業(yè)務(wù)處理方面 Node.js 則是一個(gè)可擴(kuò)展、高性能的平臺(tái)踪宠。
- 跨平臺(tái)
起初 Node.js 只能運(yùn)行于 Linux 平臺(tái)自赔,在 v0.6.0 版本后得益于 Libuv 的支持可以在 Windows 平臺(tái)運(yùn)行。
Node.js 適用于什么
講了這么多那么談下 Node.js 適合什么場景柳琢?
- I/O 密集型場景
Node.js 的優(yōu)勢主要在于事件循環(huán)绍妨,非阻塞異步 I/O,只開一個(gè)線程柬脸,不會(huì)每個(gè)請求過來我都去創(chuàng)建一個(gè)線程他去,從而產(chǎn)生資源開銷。
- ResutFul API
通常我們可以使用 Node.js 來做為中間層倒堕,負(fù)責(zé)組裝數(shù)據(jù)提供 API 接口給到前端調(diào)用灾测,這些數(shù)據(jù)源可能來自第三方接口或者數(shù)據(jù)庫,例如垦巴,以前可能我們通過后端 Java媳搪、PHP 等其它語言來做,現(xiàn)在我們前端工程師通過 Node.js 即可完成骤宣,后端則可以更專注于業(yè)務(wù)開發(fā)秦爆。
既然提到了 ResultFul API,順便推薦一個(gè)去哪兒開源的 API 管理工具 YAPI:https://github.com/YMFE/yapi 使用的 Node.js 進(jìn)行開發(fā)的(聲明下這里不是打廣告憔披,只是這個(gè)用起來真的很贊等限!忍不住向給大家推薦!)芬膝。
- RPC 服務(wù)
RPC(Remote Procedure Call)中文名「遠(yuǎn)程過程調(diào)用」望门,也許你對它很陌生,但是在當(dāng)今微服務(wù)模式下锰霜,我們可能是針對功能或者具體的業(yè)務(wù)形態(tài)進(jìn)行服務(wù)化筹误,那么服務(wù)之間的通信一種常見的模式我們都知道通過 HTTP 來實(shí)現(xiàn),了解網(wǎng)絡(luò)模型的同學(xué)可能知道癣缅,如果我們現(xiàn)在通過 TCP 的方式是不是會(huì)更高效呢纫事?
當(dāng)然是的,HTTP 屬于應(yīng)用層協(xié)議所灸,在這之下就是傳輸層丽惶,顯然以 TCP 形式是很有優(yōu)勢的,RPC 服務(wù)也就是采用的 TCP爬立,現(xiàn)在出名的 RPC 服務(wù)例如钾唬,Google 的 gRPC、阿里的 Dubbo。
- 基礎(chǔ)工具
可以做為基礎(chǔ)工具抡秆,前端領(lǐng)域中的編譯器奕巍、構(gòu)建工具、搭建腳手架等儒士。比較出名的例如 Webpack的止、Gulp 都是很成功的。
- 論壇社區(qū)
Nodeclub 是使用 Node.js 和 MongoDB 開發(fā)的社區(qū)系統(tǒng)着撩,界面優(yōu)雅诅福,功能豐富,小巧迅速拖叙,可以用它搭建自己的社區(qū)氓润。Cnode 社區(qū)就是一個(gè)成功的例子,Cnode 地址:https://cnodejs.org/
https://github.com/cnodejs/nodeclub
- Backend For Frontend
Backend For Frontend薯鳍,簡稱 BFF咖气,服務(wù)于前端的后端,并非是一種新技術(shù)只是一種邏輯上的分層挖滤,在這一層我們可以做一些資源的整合崩溪,例如:原先前端需要從三個(gè)不同的地方來獲取資源,那么斩松,有了這一層之后悯舟,我們是不是可以做個(gè)聚合,統(tǒng)一處理之后返回給前端砸民,同時(shí)也不授后端系統(tǒng)的變遷,導(dǎo)致也要去更改奋救。
- Serverless
這將是未來經(jīng)常會(huì)聽到的一個(gè)詞岭参,ServerLess 是一種 “無服務(wù)器架構(gòu)”,它不需要開發(fā)者去關(guān)心運(yùn)維尝艘、流量處理這些工作演侯,開發(fā)者則可以更關(guān)注于業(yè)務(wù)本身。
函數(shù)即服務(wù)背亥,那么寫一個(gè)函數(shù)就可以實(shí)現(xiàn)一個(gè) API 接口給到前端秒际,顯然對開發(fā)工作是減輕了很多,在 JavaScript 中函數(shù)則是一等一的公民狡汉,在 ServerLess 這一場景下 Node.js 本身也很輕量級娄徊,還是擁有著很大的優(yōu)勢。
- Microservices
微服務(wù)也是近兩年一個(gè)很火熱的詞盾戴,這里提幾個(gè)微服務(wù)主要的特點(diǎn):小型服務(wù)寄锐、以獨(dú)立進(jìn)程運(yùn)行、可以使用不同語言。那么這里則可以根據(jù)業(yè)務(wù)形態(tài)來選擇不同的語言實(shí)現(xiàn)橄仆,Node.js 本身也是很輕量級的剩膘,實(shí)現(xiàn)起來也很快,在一些 I/O 密集場景還是很適用的盆顾。
什么場景選擇什么工具怠褐,沒有最好的只有更合適的!
為什么選擇 Node.js
談一些個(gè)人感受及經(jīng)歷您宪,其實(shí)接觸計(jì)算機(jī)行業(yè)說不晚也不早奈懒,在高中階段開始接觸的編程,在接觸 Node.js 之前也學(xué)過很多編程語言蚕涤,大致曲線是這樣的 VB(這個(gè)是在高中時(shí)期)筐赔、C、C#(.Net)揖铜、Java茴丰、PHP 這些都是在學(xué)校的時(shí)候沒事玩弄的,還有接觸到前端天吓,真的很雜贿肩,但沒有一樣精通的,這也是最可怕的龄寞,在大三暑假去了北京一家公司在那里實(shí)習(xí)了兩個(gè)月 PHP汰规,但是之間有遇見做 Node.js 的同學(xué),當(dāng)時(shí)很好奇物邑,哇奧溜哮,這是什么東東,竟然可以讓 JavaScript 做后端色解,就是沒見過市面那種茂嗓。后來簡單的做了了解,回到學(xué)校之后開始學(xué)習(xí) Node.js 網(wǎng)上找各種資料看科阎,陰差陽錯(cuò)吧述吸,就這樣選擇了 Node.js 直到現(xiàn)在,其實(shí)語言只是一種工具锣笨,例如在后端中蝌矛,拋開語言這一層,還有很多東西是需要我們?nèi)ゲ粩鄬W(xué)習(xí)的错英。
最后一點(diǎn)建議:不要給自己設(shè)定邊界入撒,例如:我一定要學(xué)習(xí) Node.js 或者我一定要學(xué)習(xí) Java 又或者 Python,其實(shí)在有條件的情況下可以多接觸一些其它東西椭岩,一方面擴(kuò)展了自己的邊界衅金,另一方面自己也可以從中獲取收益噪伊。
Node.js 技術(shù)棧學(xué)習(xí)指南路線圖
這是最近畫的一張 Node.js 技術(shù)棧學(xué)習(xí)指南路線圖,從中可以看出拋開語言這一層面氮唯,剩下的都是我們要學(xué)習(xí)的鉴吹。歡迎大家關(guān)注公眾號(hào)「Nodejs技術(shù)棧」專注于 Node.js 相關(guān)技術(shù)棧研究分享,若有 Node.js 相關(guān)文章也歡迎大家投稿惩琉!共同成長豆励!