node異步I/O

讓I/O與CPU計算并行

Node 在*nix平臺洒忧,通過線程池實現(xiàn)(主線程和I/O線程)剖膳,在windows下使用IOCP(調(diào)用異步方法碘举,等待I/O完成后通知茎匠,執(zhí)行回調(diào)格仲,內(nèi)部也依靠線程池,但由系統(tǒng)內(nèi)核管理)诵冒,通過libuv層來兼容凯肋。

Node本身是多線程的,但其中的JavaScript是單線程汽馋、因為v8的限制侮东,但計算之類的都是在此線程,多線程只是I/O(磁盤豹芯,網(wǎng)絡(luò)等)悄雅,I/O有另外的線程池

事件循環(huán)

  • Node自身的執(zhí)行模型,在libuv中

  • 在Node啟動時,創(chuàng)建一個類似while(true)的循環(huán)铁蹈,每循環(huán)一次成一個Tick,每次Tick查看是否有事件要處理宽闲,若有就處理事件和它的相關(guān)回調(diào)函數(shù)。在windows中基于IOCP,在*nix中基于多線程

  • 在Tick過程中通過觀察者判斷是否有事件要處理

  • 異步過程中最重要的就是請求對象握牧,所有狀態(tài)容诬、傳入?yún)?shù)、當(dāng)前方法和回調(diào)函數(shù)都封裝在此沿腰,javascript將對象組裝好览徒,送入I/O線程池后就結(jié)束了,I/O操作在線程池中等待請求對象被執(zhí)行

  • Tick在執(zhí)行過程中檢查線程池中是否有執(zhí)行完的請求矫俺,并加入I/O觀察者隊列中吱殉,然后再從觀察者取到可用的請求對象當(dāng)做事件處理掸冤,取出對象中的回調(diào)函數(shù)執(zhí)行,若有業(yè)務(wù)層callback再給js執(zhí)行

IO異步.png

事件驅(qū)動的高性能服務(wù)器

基于事件驅(qū)動的非阻塞I/O模型
通過主循環(huán)加載事件觸發(fā)的方式來運行程序處理請求,無需為每一個請求創(chuàng)建額外的對應(yīng)線程:操作系統(tǒng)因為線程少友雳,所以在上下文切換時代價很小稿湿,有助系統(tǒng)穩(wěn)定處理大量請求(但不適合密集運算),但用戶代碼不能并行執(zhí)行押赊,I/O可以

  • 單線程保證運行安全,避免重入
Smaller icon
Smaller icon

另外一些異步api

定時器

  • setTimeout()單次定時執(zhí)行 setInterval()多次定時執(zhí)行

原理和異步I/O類似流礁,將創(chuàng)建的定時器放到定時器觀察者內(nèi)部的紅黑樹,tick執(zhí)行時神帅,從紅黑樹中迭代取出定時器對象再姑,檢查是否超過定時時間,超過就形成事件并且立刻執(zhí)行回調(diào)函數(shù)找御。

問題:定時不精確,如果某個循環(huán)占用時間過多霎桅,當(dāng)再輪到定時器執(zhí)行時就已經(jīng)超時了

process.nextTick()

  • 若想立即異步執(zhí)行一個任務(wù),用這個更高效
setTimeout(function () { // TODO
}, 0);// 比較浪費性能

process.nextTick=function(callback){
    if(process._exiting) return;
    if(tickDepth >=process.maxTickDepth)
       maxTickWarn();
    var tock={callback:callback};
    if(process.domain) tock.domain=process.domain;
     nextTickQueue.push(tock);
    if(nextTickQueue.length){
      process._needTickCallback();
    }
}

調(diào)用process.nextTick(),只會將回調(diào)函數(shù)放入隊列中滔驶,在下個Tick取出

setImmediate()

  • 類process.nextTick() 將回調(diào)函數(shù)延時執(zhí)行遇革,建議使用這個(v0.9.1以后)
process.nextTick(function(){
    console.log('nextTick延時執(zhí)行1')
});
process.nextTick(function(){
    console.log('nextTick延時執(zhí)行2');
});
setImmdiate(function(){
    console.log('setImmdiate延時執(zhí)行1');
    process.nextTick(function(){
    console.log('強勢插入');
    })
});  
setImmediate(function () {
    console.log('setImmediate延時執(zhí)行2'); 
});
console.log('正常執(zhí)行');

//正常執(zhí)行 
//nextTick  延時執(zhí)行1 
//nextTick  延時執(zhí)行2 
//setImmediate  延時執(zhí)行1  
//強勢插入 
//setImmediate  延時執(zhí)行2

process.nextTick()屬于idle觀察者,setImmediate()屬于check觀察者揭糕,在每輪循環(huán)中,idle觀察者先于I/O觀察者先與check

process.nextTick()的回調(diào)函數(shù)保存在數(shù)組中,在每輪循環(huán)中會將數(shù)組中的回調(diào)函數(shù)全部執(zhí)行完插佛。setImmediate()保存在鏈表中,在每輪循環(huán)中執(zhí)行鏈表的一個回調(diào)函數(shù)

異步并發(fā)控制

并發(fā)量過大,下層服務(wù)器會吃不消

bagpipe
  1. 通過隊列控制并發(fā)量
  2. 在當(dāng)前活躍的異步調(diào)用量小于限定值,從隊列中取出執(zhí)行
  3. 活躍調(diào)用達(dá)到限定值后氢拥,調(diào)用暫存在隊列中
  4. 每個調(diào)用結(jié)束時锨侯,從隊列中取出新的異步調(diào)用執(zhí)行
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市囚痴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌深滚,老刑警劉巖涣觉,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件血柳,死亡現(xiàn)場離奇詭異,居然都是意外死亡膝宁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門员淫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來击敌,“玉大人,你說我怎么就攤上這事沃斤。” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵组去,是天一觀的道長。 經(jīng)常有香客問我诚撵,道長键闺,這世上最難降的妖魔是什么寿烟? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任辛燥,我火速辦了婚禮,結(jié)果婚禮上挎塌,老公的妹妹穿的比我還像新娘徘六。我一直安慰自己,他們只是感情好待锈,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布嘴高。 她就那樣靜靜地躺著和屎,像睡著了一般春瞬。 火紅的嫁衣襯著肌膚如雪柴信。 梳的紋絲不亂的頭發(fā)上快鱼,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音抹竹,去河邊找鬼。 笑死窃判,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的询件。 我是一名探鬼主播唆樊,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逗旁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起片效,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤淀衣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后膨桥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡陵吸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年介牙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡剩拢,死狀恐怖饶唤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情募狂,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布性穿,位于F島的核電站,受9級特大地震影響需曾,放射性物質(zhì)發(fā)生泄漏祈远。R本人自食惡果不足惜呆万,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一谋减、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逃顶,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽技矮。三九已至殊轴,卻和暖如春衰倦,著一層夾襖步出監(jiān)牢的瞬間旁理,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工驻襟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沉衣。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像豌习,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子既荚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

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

  • 單線程編程會因阻塞I/O導(dǎo)致硬件資源得不到更優(yōu)的使用巷屿。多線程編程也因為編程中的死鎖、狀態(tài)同步等問題讓開發(fā)人員頭痛嘱巾。...
    exialym閱讀 431評論 0 1
  • 參考:IOCP原理Philip Roberts: Help, I’m stuck in an event-loop...
    mary_s閱讀 2,235評論 1 8
  • Node的異步I/O 我們?yōu)槭裁葱枰惒絀/O旬昭? 用戶體驗服務(wù)器端如果基于同步執(zhí)行的,隨著應(yīng)用復(fù)雜性的增加问拘,響應(yīng)的...
    俗三瘋閱讀 490評論 0 0
  • 1 nodejs 中的異步存在嗎? 現(xiàn)在有點 javascript 基礎(chǔ)的人都在聽說過 nodejs 绪杏,而只要與 ...
    htoo閱讀 6,473評論 4 51
  • 看到很多文件介紹關(guān)于Node.js中的事件循環(huán)纽绍,但是總是有些地方不是很理解蕾久,最近無意中看到了Node官方文檔中對事...
    勤勞的小葉閱讀 3,245評論 0 5