知識總結與整理:Node.js專題二(Node主要特性)

如果我們平常有瀏覽有關Node.js的文章,估計我們都會聽到最多關于Node.js是異步非阻塞I/O,單線程悲酷,事件機制。本章節(jié)主要去深入探討這幾種特性(PS:本文是對所學知識的學習和總結,可能存在理解錯誤借嗽。請帶著懷疑的眼光琳轿,同時如果有錯誤希望能指出判沟。)

章節(jié)二.png

一、Node.js的異步I/O崭篡,非阻塞I/O

首先我們先來理解幾個概念:阻塞IO(blocking I/O)非阻塞IO(non-blocking I/O)挪哄、同步IO(synchronous I/O)異步IO(synchronous I/O)

問題:這里肯定有人想問琉闪,異步I/O和非阻塞I/O不是一回事嗎迹炼??

答案:異步I/O和非阻塞I/O根本不是同一回事颠毙,曾經筆者一直天真的以為非阻塞I/O就是異步I/O T_T(直到看見樸靈大神的深入淺出Node.js)斯入。

1.現(xiàn)在我們來了解什么是異步I/O,什么是同步I/O蛀蜜?

這里轉自有趣的知乎er
老張愛喝茶刻两,廢話不說,煮開水涵防。出場人物:老張闹伪,水壺兩把(普通水壺,簡稱水壺壮池;會響的水壺偏瓤,簡稱響水壺)。
1:老張把水壺放到火上椰憋,立等水開厅克。(同步阻塞)老張覺得自己有點傻
2: 老張把水壺放到火上,去客廳看電視橙依,時不時去廚房看看水開沒有证舟。(同步非阻塞)老張還是覺得自己有點傻硕旗,于是變高端了,買了把會響笛的那種水壺女责。水開之后漆枚,能大聲發(fā)出嘀~~~~的噪音。
3:老張把響水壺放到火上抵知,立等水開墙基。(異步阻塞)老張覺得這樣傻等意義不大
4: 老張把響水壺放到火上,去客廳看電視刷喜,水壺響之前不再去看它了残制,響了再去拿壺。(異步非阻塞)老張覺得自己聰明了掖疮。
所謂同步異步初茶,只是對于水壺而言。普通水壺浊闪,同步恼布;響水壺,異步规揪。雖然都能干活桥氏,但響水壺可以在自己完工之后,提示老張水開了猛铅。這是普通水壺所不能及的字支。同步只能讓調用者去輪詢自己(情況2中),造成老張效率的低下奸忽。
所謂阻塞非阻塞堕伪,僅僅對于老張而言。立等的老張栗菜,阻塞欠雌;看電視的老張,非阻塞疙筹。情況1和情況3中老張就是阻塞的富俄,媳婦喊他都不知道。雖然3中響水壺是異步的而咆,可對于立等的老張沒有太大的意義霍比。所以一般異步是配合非阻塞使用的,這樣才能發(fā)揮異步的效用暴备。
作者:愚抄
鏈接:https://www.zhihu.com/question/19732473/answer/23434554
來源:知乎
著作權歸作者所有悠瞬。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。

二浅妆、單線程

在專題一的介紹望迎,我們指導Node.js的runtime是V8,而V8設計是為了讓Chrome瀏覽器對Javascript語言進行編譯和解析的凌外,另外有過JS經驗的工程師都知道辩尊,JS的最大特點是單線程,而Node.js對V8的延用也是針對這一非常重要的特點趴乡。那么什么是單線程,單線程指的是对省,一個進程只能擁有一個線程,程序按順序執(zhí)行晾捏,只有等到前面的程序執(zhí)行完畢,才能執(zhí)行下一個!來看看Node對Http服務的模型哀托,

node_http_model.png

Node.js單線程指的是主線程是單線程惦辛,由主線程按照編碼順序一步步執(zhí)行,當主線程遇到阻塞的時候仓手,后續(xù)的程序就會被卡住無法執(zhí)行胖齐。說了這么多,不如來實踐一下驗真假:

實驗.png

先將index.js的代碼改成這樣嗽冒,然后打開瀏覽器呀伙,你會發(fā)現(xiàn)瀏覽器在10秒之后才做出反應,打出Hello Node.js

堆棧圖.png

JavaScript是解析性語言添坊,代碼按照編碼順序一行一行被壓進stack里面執(zhí)行剿另,執(zhí)行完成后移除然后繼續(xù)壓下一行代碼塊進去執(zhí)行。上面代碼塊的堆棧圖贬蛙,當主線程接受了request后雨女,程序被壓進同步執(zhí)行的sleep執(zhí)行塊(我們假設這里就是程序的業(yè)務處理),如果在這10s內有第二個request進來就會被壓進stack里面等待10s執(zhí)行完成后再進一步處理下一個請求阳准,后面的請求都會被掛起等待前面的同步執(zhí)行完成后再執(zhí)行氛堕,所以這也說明Node.js單線程的執(zhí)行模型,因為這樣的特性野蝇,我們的頁面不能有耗時很長的同步處理程序阻塞了程序的后續(xù)執(zhí)行讼稚,而對于耗時過長的程序應該采用異步執(zhí)行,這里也就是Node.js的第二個特性绕沈,異步锐想。

三、異步

我們平時說的Node.js是異步的七冲,那么具體是指那部分異步,而答案是主線程的異步處理函數(shù)隊列+多線程異步I/O

1.主線程的異步處理函數(shù)隊列

上面那句話看上去是不是有點抽象難懂痛倚,現(xiàn)在來進行解釋,所謂主線程異步處理函數(shù)隊列是指主線程的主要執(zhí)行空間除了stack(執(zhí)行棧)head(產生堆)外澜躺,還會callback queue(回調函數(shù)隊列),而callback queue是存放了異步處理的回調函數(shù)蝉稳,當一個異步I/O處理完抒蚜,就會向callback queue存放一個回調函數(shù),當stack里面的程序執(zhí)行完耘戚,主線程就會從callback queue取出已經存放好的回調函數(shù)去執(zhí)行嗡髓,而我們平時最常見的異步,除了事件外收津,還有timer饿这,例如setTimeout,不如我們舉一個栗子~

let sleep = (time)=>{
    let exit = Date.now+time*1000;
    while(Date.now()<exit){};
    console.log('end sleep')
    return
}

let main = ()=>{
    setTimeout(()=>{
         console.log('setTimeout run');
    },0)
    sleep(5);
    console.log('after sleep');
}

main()

執(zhí)行輸出:
end sleep
after sleep
undefined(由于每個函數(shù)執(zhí)行完都會自行return撞秋,如果沒指定长捧,就會輸出undefined,這個是main執(zhí)行完return出來的)
setTimeout run

下面是代碼塊的主線程堆棧執(zhí)行:

異步.png

看上圖吻贿,主線程將main函數(shù)壓進stack里面一行行解析執(zhí)行串结,首先遇到setTimeout方法,因為setTimeout是一個異步處理函數(shù)舅列,這里會setTimeout(callback,timeout)肌割,里面的callback函數(shù)移進callback queue里面,同時會把自己從主線程的stack里面移除帐要,繼續(xù)壓進后面的執(zhí)行代碼來解析執(zhí)行把敞,這里繼續(xù)壓進sleep沉睡5s,接下來執(zhí)行console榨惠,等到這里的同步代碼執(zhí)行完成后這個時候就會從callback queue里面取回調函數(shù)一個個執(zhí)行亡哄。(題外話:就算setTimeout里面的timeout設置了是0政鼠,都是要等待執(zhí)行塊里面的同步代碼執(zhí)行完成后再去執(zhí)行callback queue里面的代碼)這就是異步里面的其一:主線程異步函數(shù)處理隊列。(PS,setTimeout的回調函數(shù)的執(zhí)行時間不是當前隊列,而是下一個執(zhí)行隊列狡耻,即是是設置為偶洋,也最多是下一次執(zhí)行隊列第一個執(zhí)行版保,詳情阮一峰JS運行機制)

2.多線程異步I/O

這里可能有人會有疑問洲愤,買賣皮喔!你不是說Node.js是單線程嗎横侦,你這不是自己打臉嗎?我想說挥萌,這里其實是沒有沖突的,Node.js每個進程里面只有一個主線程來處理程序枉侧。因此引瀑,主線程是單線程,而主線程之外調用的I/O處理是通過一個叫做線程池的結構來管理的榨馁,所以I/O的處理是多線程的憨栽,而主線程和I/O線程池則通過上面剛剛講述的主線程的異步處理函數(shù)隊列來協(xié)作。(PSNode.js只對文件系統(tǒng)以及DNS實現(xiàn)了多線程I/O封裝,網絡I/O還是采用單線程形式)如圖:

多線程.png

上圖在主線程中屑柔,當遇到需要處理的I/O時屡萤,就將I/O的處理放在I/O線程池中管理,而主線程繼續(xù)執(zhí)行掸宛,當I/O線程池中有I/O完成了死陆,就會想callback queue注冊回調函數(shù)等待主線程執(zhí)行,而Node.js的高性能也是得益于其將阻塞的I/O異步化唧瘾,使得不影響主邏輯的執(zhí)行措译。

四、事件驅動

文章至此饰序,我們先進行總結领虹,Node.js至此我們簡介了兩個主要特性,單線程菌羽,異步,每個Node程序只會在主線程中執(zhí)行程序代碼掠械,在執(zhí)行過程中將阻塞的I/O操作異步化,將放至I/O線程池中進行管理注祖,當線程池中有I/O操作完成,就會向callback queue注冊回調函數(shù)均唉,等待同步邏輯執(zhí)行完成后再通過callback queue里面取出回調函數(shù)壓進stack里面執(zhí)行是晨,好了,而事件驅動的作用就是取出回調函數(shù)舔箭。事件驅動又叫事件循環(huán)罩缴,是指主線程從主線程的異步處理函數(shù)隊列里面不停循環(huán)的讀取事件,驅動了所有的異步回調函數(shù)的執(zhí)行层扶。詳情Node事件輪詢

事件機制.png

至此整個Node.js的異步化邏輯可以不斷循環(huán)的跑起來了箫章,以上則是我們日常所言的Node.js的三大特性以及其原理。

參考資料:
Node事件輪詢
JS運行機制
Node.js特性分析
非阻塞I/O和異步I/O的區(qū)別

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末镜会,一起剝皮案震驚了整個濱河市檬寂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戳表,老刑警劉巖桶至,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匾旭,居然都是意外死亡镣屹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門价涝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來女蜈,“玉大人,你說我怎么就攤上這事∥苯眩” “怎么了逸寓?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惰许。 經常有香客問我席覆,道長,這世上最難降的妖魔是什么汹买? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任佩伤,我火速辦了婚禮,結果婚禮上晦毙,老公的妹妹穿的比我還像新娘生巡。我一直安慰自己,他們只是感情好见妒,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布孤荣。 她就那樣靜靜地躺著,像睡著了一般须揣。 火紅的嫁衣襯著肌膚如雪盐股。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天耻卡,我揣著相機與錄音疯汁,去河邊找鬼。 笑死卵酪,一個胖子當著我的面吹牛幌蚊,可吹牛的內容都是我干的。 我是一名探鬼主播溃卡,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼溢豆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瘸羡?” 一聲冷哼從身側響起漩仙,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎最铁,沒想到半個月后讯赏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡冷尉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年漱挎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雀哨。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡磕谅,死狀恐怖私爷,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情膊夹,我是刑警寧澤衬浑,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站放刨,受9級特大地震影響工秩,放射性物質發(fā)生泄漏。R本人自食惡果不足惜进统,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一助币、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧螟碎,春花似錦眉菱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酥郭,卻和暖如春华坦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背不从。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工季春, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人消返。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像耘拇,于是被迫代替她去往敵國和親撵颊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內容