node核心特性理解

原文地址在我的博客神僵,轉(zhuǎn)載請(qǐng)注明來源酌心,謝謝!

node是在前端領(lǐng)域經(jīng)程敉悖看到的詞。node對(duì)于前端的重要性已經(jīng)不言而喻墩崩,掌握node也是作為合格的前端工程師一項(xiàng)基本功了氓英。知道node、知道后端的一些東西鹦筹,才能更好的與別人合作铝阐,發(fā)揮更大的價(jià)值。

概述

本文主要介紹了我對(duì)node的一些核心特性的理解铐拐,包括node架構(gòu)徘键、特點(diǎn)、機(jī)制遍蟋、核心模塊與簡單應(yīng)用吹害。

正文

從瀏覽器到node

首先,node是一個(gè)平臺(tái)虚青,使用javascript作為編程語言它呀,運(yùn)行在服務(wù)端。服務(wù)端語言能做的棒厘,node一般都能做纵穿,而且有些情況下做的更好,因?yàn)樗哂凶约旱奶厣?/p>

node是javascript運(yùn)行環(huán)境(runtime)奢人,就像瀏覽器一樣谓媒,是一個(gè)平臺(tái)。在瀏覽器中何乎,V8引擎負(fù)責(zé)解釋javascript句惯,你在javascript調(diào)用的接口都是瀏覽器實(shí)現(xiàn)并提供的,瀏覽器會(huì)調(diào)用底層的支救、由其他語言(C++)實(shí)現(xiàn)并封裝好的接口來完成任務(wù)宗弯;同樣,在node中搂妻,也是V8引擎負(fù)責(zé)解釋javascript蒙保,而你在javascript調(diào)用的瀏覽器提供的接口就不能用了,因?yàn)樗撾x了瀏覽器的環(huán)境欲主,但是因?yàn)槟阍趎ode環(huán)境中邓厕,你就可以使用node提供的由C++語言實(shí)現(xiàn)的逝嚎、由javascript封裝好的各種接口來完成后端任務(wù)。瀏覽器提供的API用于處理前端任務(wù)详恼,比如彈個(gè)窗补君,換個(gè)主題,處理用戶操作等昧互,而node因?yàn)榉?wù)后端挽铁,因此提供的API則用來處理后端任務(wù),比如響應(yīng)請(qǐng)求敞掘,讀取文件等叽掘,這些API由不同的模塊提供。因?yàn)殛P(guān)注領(lǐng)域不一樣玖雁,因此所做的任務(wù)就不一樣更扁,提供的API就不一樣,但是原理赫冬、相關(guān)實(shí)現(xiàn)大致與瀏覽器端相同浓镜。

從瀏覽器到node這一塊如果想了解更多,推薦IBM的文章node.js到底是什么劲厌?

node 架構(gòu)

node架構(gòu)分為三層(參考鏈接):

圖片來源

  • Node standard library:node標(biāo)準(zhǔn)庫膛薛,也就是node模塊提供各種接口的javascript實(shí)現(xiàn),任何javascript代碼补鼻、npm install 或者你寫的模塊都在這里
  • Node bindings:包括C/C++ bindings(膠水代碼)和Add on(添加其他C/C++庫時(shí)需要自己寫的Bindings)相叁,這一層向下封裝了V8和libuv接口,向上提供了基礎(chǔ)API接口辽幌,是連接javascript和C++的橋梁
  • 第三層是支撐 Node.js 運(yùn)行的關(guān)鍵增淹,由 C/C++ 實(shí)現(xiàn)。
    • V8 是Google開發(fā)的JavaScript引擎乌企,提供JavaScript運(yùn)行環(huán)境虑润,可以說它就是 Node.js 的發(fā)動(dòng)機(jī),負(fù)責(zé)解釋javascript加酵,與chrome瀏覽器相同拳喻。
    • Libuv 是專門為Node.js開發(fā)的一個(gè)封裝庫,提供跨平臺(tái)的異步I/O能力猪腕,負(fù)責(zé)node運(yùn)行時(shí)的線程池調(diào)度冗澈。
    • C-ares:提供了異步處理 DNS 相關(guān)的能力。
    • http_parser陋葡、OpenSSL亚亲、zlib 等:提供包括 http 解析、SSL、數(shù)據(jù)壓縮等系統(tǒng)底層的訪問捌归。

平常我們用到的也就是第一層node各個(gè)模塊實(shí)現(xiàn)的接口肛响。

那他們之間時(shí)如何協(xié)作的呢

javascript主線程

程序啟動(dòng),V8引擎會(huì)首先解析javascript代碼惜索,通過Node bindings來調(diào)用C/C++庫特笋。執(zhí)行到當(dāng)前事件時(shí),會(huì)把事件放在調(diào)用堆棧(stack和heap)處理(可以理解為放進(jìn)一個(gè)工作空間巾兆,如上圖)猎物,在堆棧中的任何I/O請(qǐng)求都會(huì)交給libuv來處理,libuv維持一個(gè)線程池角塑,里面是一些工作線程(如下圖)蔫磨,請(qǐng)求會(huì)調(diào)用這些線程來完成任務(wù),這些線程則調(diào)用底層的C/C++庫吉拳。完成時(shí),libuv再把結(jié)果返回事件隊(duì)列等待主線程執(zhí)行适揉。在此期間留攒,主線程繼續(xù)執(zhí)行其他任務(wù)。

node 執(zhí)行特性

單線程嫉嘀、非阻塞型I/O

單線程的意思就是只在一個(gè)線程上運(yùn)行javascript炼邀。首先,javascript 在瀏覽器端是單線程的剪侮,這是為了避免多線程產(chǎn)生任務(wù)沖突的情況拭宁;其次,java和PHP這類多線程后端語言瓣俯,為避免同步I/O阻塞杰标,每處理一個(gè)連接都會(huì)產(chǎn)生一個(gè)新線程,這樣的話在遇到大量并發(fā)請(qǐng)求時(shí)就會(huì)受到物理內(nèi)存的限制彩匕。node 延續(xù)了瀏覽器端單線程javascript腔剂,只用一個(gè)主線程執(zhí)行javascript,不斷循環(huán)遍歷事件隊(duì)列驼仪,執(zhí)行事件掸犬。事實(shí)上,主線程發(fā)出的I/O請(qǐng)求绪爸,都會(huì)交給其他線程去完成湾碎,其他線程完成后悔返回結(jié)果放到事件隊(duì)列。在此期間奠货,主線程會(huì)繼續(xù)執(zhí)行其他任務(wù)介褥,也就是在交給libuv后直接返回,繼續(xù)執(zhí)行下面的任務(wù),主線程只負(fù)責(zé)循環(huán)執(zhí)行事件隊(duì)列呻顽,因此這種模式稱為非阻塞型I/O雹顺,性能很好,適用于處理大量并發(fā)請(qǐng)求廊遍,還能簡化開發(fā)嬉愧。

事件驅(qū)動(dòng)機(jī)制

還是跟瀏覽器的差不多『砬埃總的來說就是没酣,瀏覽器端把鼠標(biāo)點(diǎn)擊、鍵盤按鍵等定義為事件卵迂,而node把網(wǎng)絡(luò)請(qǐng)求裕便、I/O操作等也看作事件,嚴(yán)格來說见咒,一切動(dòng)作都是事件偿衰,這就是事件驅(qū)動(dòng)的思想。在程序啟動(dòng)時(shí)改览,便進(jìn)入事件循環(huán)下翎,不斷遍歷執(zhí)行事件隊(duì)列中產(chǎn)生的事件,而在執(zhí)行過程中宝当,又會(huì)產(chǎn)生新的事件视事,因此稱為事件循環(huán)。主線程執(zhí)行事件時(shí)庆揩,遇到麻煩的I/O請(qǐng)求會(huì)交給libuv來調(diào)度其他工作線程來幫忙俐东,忙完后就會(huì)形成事件返回結(jié)果到事件隊(duì)列等待主線程處理。在此期間订晌,主線程會(huì)繼續(xù)執(zhí)行其他任務(wù)虏辫。

mbp 曾經(jīng)做過一個(gè)巧妙的比喻,把 Node.js 看成一家餐廳锈拨。我在此借用下他的例子乒裆,稍作修改來闡述下 Node.js 的執(zhí)行情況:

把 Node.js 應(yīng)用程序想象成一家星巴克,一個(gè)訓(xùn)練有素的前臺(tái)服務(wù)生(唯一的主線程)在柜臺(tái)前接受訂單推励。當(dāng)很多顧客同時(shí)光臨的時(shí)候鹤耍,他們排隊(duì)(進(jìn)入事件隊(duì)列)等候接待;每當(dāng)服務(wù)生接待一位顧客验辞,服務(wù)生會(huì)把訂單告知給經(jīng)理(libuv)稿黄,經(jīng)理安排相應(yīng)的專職人員去烹制咖啡(工作線程或者系統(tǒng)特性)。這個(gè)專職人員會(huì)使用不同的原料和咖啡機(jī)(底層 C/C++ 組件)按訂單要求制作咖啡或甜點(diǎn)跌造,通常會(huì)有四個(gè)這樣的專職人員保持在崗待命(線程池)杆怕,高峰期的時(shí)候也可以安排更多(不過需要在一早就安排人員來上班族购,而不能中午臨時(shí)通知)。服務(wù)生把訂單轉(zhuǎn)交給經(jīng)理之后不需要等著咖啡制作完成陵珍,而是直接開始接待下一位顧客(事件循環(huán)放進(jìn)調(diào)用堆棧的另一個(gè)事件)寝杖,你可以把當(dāng)前調(diào)用堆棧里的事件看成是站在柜臺(tái)前正在接受服務(wù)的顧客。

當(dāng)咖啡完成時(shí)互纯,會(huì)被發(fā)送到顧客隊(duì)列的最后位置瑟幕,等它移動(dòng)到柜臺(tái)前服務(wù)生會(huì)叫相應(yīng)顧客的名字,顧客就來取走咖啡(最后這部分在真實(shí)生活中聽起來有點(diǎn)怪留潦,不過你從程序執(zhí)行的角度理解就比較合乎情理了)只盹。

? ——By Amio

如果你想進(jìn)一步了解javascript 事件驅(qū)動(dòng)機(jī)制,推薦深入理解 javascript 事件循環(huán)機(jī)制

node 模塊

node 模塊機(jī)制是CommonJs 的實(shí)現(xiàn)兔院。起初殖卑,javascript 標(biāo)準(zhǔn)一片混沌,并沒有其他成熟語言(例如C++)的模塊機(jī)制坊萝、標(biāo)準(zhǔn)庫孵稽、接口等,為了讓javascript 具備開發(fā)大型應(yīng)用的能力十偶,為了讓 javascript 能在后端運(yùn)行菩鲜,CommonJS 就制定了javascript 模塊規(guī)范。node 借鑒了這個(gè)規(guī)范扯键,讓javascript 以模塊形式組織起來睦袖。模塊機(jī)制是一個(gè)成熟語言必備的珊肃,一個(gè)模塊代表一個(gè)功能的封裝荣刑,它就像搭積木一樣,不同模塊可以銜接在一塊伦乔,使語言具有極強(qiáng)的可擴(kuò)展型厉亏。node 模塊機(jī)制同時(shí)制定了模塊規(guī)范,能讓全球的開發(fā)者都可以在node官網(wǎng)上傳自己的包烈和。此外爱只,node 社區(qū)又實(shí)現(xiàn)了node 包管理器npm,使用npm可以輕松管理各種包招刹。

node 的模塊分為核心模塊和用戶模塊恬试,前者是底層的、自帶的疯暑,后者是第三方训柴。

核心模塊有Global(全局對(duì)象)、Http妇拯、fs(文件系統(tǒng))幻馁、Buffer洗鸵、Stream、Events仗嗦、URL膘滨、path等,這些模塊提供了后端服務(wù)的基本功能稀拐,都提供自己關(guān)注功能的API火邓。

在使用模塊時(shí),require 即可钩蚊。但在require背后贡翘,node 有一套尋找模塊的機(jī)制:

node require機(jī)制

從上圖可以看到,node 優(yōu)先從緩存區(qū)讀取砰逻,緩存區(qū)有直接讀取鸣驱,沒有則加載并緩存,這樣做不用一遍一遍去找了蝠咆,非常高效踊东。node 在緩存區(qū)沒有發(fā)現(xiàn)模塊時(shí),會(huì)分析require 的路徑和文件后綴刚操,node 有個(gè)模塊路徑的查找策略闸翅,我們可以在名為module_paths 的js文件里console.log(module.paths)然后node module_paths.js運(yùn)行來間接查看node 尋找文件模塊的具體文件的方式:

[ '/home/username/nodeProject/node_modules',
 '/home/username/node_modules',
 '/home/node_modules',
 '/node_modules' ] //Linux下的數(shù)組輸出(/home/username因電腦不同而異)

[ 'c:\\nodeProject\\node_modules', 'c:\\node_modules' ] //Windows

也就是按照下面的順序:

  • 當(dāng)前文件目錄下的node_modules目錄。
  • 父目錄下的node_modules目錄菊霜。
  • 父目錄的父目錄下的node_modules目錄坚冀。
  • 沿路徑向上逐級(jí)遞歸,直到根目錄下的node_modules目錄鉴逞。

這些順序都是在查找緩存之后的记某。

在找到模塊后,node 將在引入之前對(duì)這個(gè)模塊進(jìn)行編譯執(zhí)行构捡,編譯成功后會(huì)緩存液南,執(zhí)行的結(jié)果會(huì)返回給調(diào)用者。

簡單應(yīng)用

有了node 自帶核心模塊的基礎(chǔ)功能勾徽,就可以進(jìn)一步封裝更強(qiáng)大滑凉、容易操作的功能了,就像jQuery 對(duì)于javascript 基礎(chǔ)API 一樣喘帚,node 社區(qū)也誕生了像 Express畅姊、KOA等框架來構(gòu)建node.js程序

node.js開發(fā)框架

這些框架的詳情移步2017 Node.js 開發(fā)框架比較

另外,node 還可以連接MySQL吹由,MangoDB進(jìn)行數(shù)據(jù)庫操作若未。

下面是使用express 腳手架生成的基本 node應(yīng)用結(jié)構(gòu):

.
├── app.js            //程序入口
├── bin
│   └── www           //二機(jī)制文件
├── package.json      //項(xiàng)目配置文件
├── public
│   ├── images        
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js      //路由文件入口
│   └── users.js
└── views
    ├── error.jade    //界面模板
    ├── index.jade
    └── layout.jade

現(xiàn)在使用 node作為后端語言通常都要配合類庫和框架使用。

node 的單線程溉知、非阻塞型特點(diǎn)讓它非常適合高并發(fā)的應(yīng)用陨瘩,適合處理大量重復(fù)的腕够、簡單的邏輯,適合構(gòu)建Rest/JSON API服務(wù)舌劳;同時(shí)帚湘,也正是因?yàn)檫@些特性,node 不適合CPU使用率較重甚淡、IO使用率較輕的偏計(jì)算應(yīng)用大诸。缺點(diǎn)是因?yàn)閱尉€程,一個(gè)進(jìn)程掛就全掛了贯卦,可靠性低资柔,但這是可以避免的。node 更多的應(yīng)用是在前端撵割、中間件贿堰、前后端分離等。

由于 node 的諸多優(yōu)點(diǎn)啡彬,現(xiàn)在越來越多大公司開始使用node羹与、深度使用node。

總結(jié)

node 的核心概念庶灿、思想遠(yuǎn)不止這么多纵搁,應(yīng)用更是多了去了,無奈本人水平有限往踢,只能說個(gè)淺層腾誉,還有很多像進(jìn)程管理、異步編程峻呕、異常調(diào)試利职、部署、性能調(diào)優(yōu)山上、與集群眼耀、CDN協(xié)調(diào)等都值得深入探索一下英支。無論如何佩憾,node 是讓javascript 邁向企業(yè)級(jí)開發(fā)語言重要的一步(也許已經(jīng)是了),前端工程師從未像現(xiàn)在這樣的powerful干花,能做的事情越來越多妄帘,所能涉及的領(lǐng)域也越來越多。前端這行越來越令人興奮了池凄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抡驼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子肿仑,更是在濱河造成了極大的恐慌致盟,老刑警劉巖碎税,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異馏锡,居然都是意外死亡雷蹂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門杯道,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匪煌,“玉大人,你說我怎么就攤上這事党巾∥ィ” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵齿拂,是天一觀的道長驳规。 經(jīng)常有香客問我,道長署海,這世上最難降的妖魔是什么达舒? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮叹侄,結(jié)果婚禮上巩搏,老公的妹妹穿的比我還像新娘。我一直安慰自己趾代,他們只是感情好贯底,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撒强,像睡著了一般禽捆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上飘哨,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天胚想,我揣著相機(jī)與錄音,去河邊找鬼芽隆。 笑死浊服,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胚吁。 我是一名探鬼主播牙躺,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼腕扶!你這毒婦竟也來了孽拷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤半抱,失蹤者是張志新(化名)和其女友劉穎脓恕,沒想到半個(gè)月后膜宋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炼幔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年激蹲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片江掩。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡学辱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出环形,到底是詐尸還是另有隱情策泣,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布抬吟,位于F島的核電站萨咕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏火本。R本人自食惡果不足惜危队,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钙畔。 院中可真熱鬧茫陆,春花似錦、人聲如沸擎析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揍魂。三九已至桨醋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間现斋,已是汗流浹背喜最。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庄蹋,地道東北人瞬内。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蔓肯,于是被迫代替她去往敵國和親遂鹊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子振乏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Node.js是目前非痴岚火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特慧邮。 眾所周知调限,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,613評(píng)論 2 41
  • Node.js是目前非持勐剑火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特耻矮。 眾所周知秦躯,在Netscape設(shè)計(jì)出JavaScri...
    Myselfyan閱讀 4,071評(píng)論 2 58
  • 人有許多路可以選,可以走裆装。
    馬不蹄兒閱讀 347評(píng)論 0 0
  • “這么說踱承,你老婆是南方人咯?”我緊接著問道哨免。 “恩茎活。”對(duì)面的大叔靦腆的笑笑琢唾,被長年累月的油煙熏得油光滑亮的臉上綻開...
    美好的花想容閱讀 462評(píng)論 0 0
  • 黑夜中響起璀璨 恍若煙火明亮 一閃一響载荔,此起彼伏 單調(diào)而又凄涼 這絕不是人間的光 那么刺眼又無情 靈魂被收割 發(fā)出...
    淺笑大大閱讀 299評(píng)論 0 0