Node——异步I/O

单线程编程会因阻塞I/O导致硬件资源得不到更优的使用。多线程编程也因为编程中的死锁、状态同步等问题让开发人员头痛。Node在两者之间给出了它的解决方案:利用单线程,远离多线程死锁、状态同步等问题;利用异步I/O,让单线程远离阻塞,以好使用CPU。

异步IO的实现

在Node中,JS是在单线程中执行的没错,但是内部完成IO工作的另有线程池,使用一个主进程和多个IO线程来模拟异步IO。
当主线程发起IO调用时,IO操作会被放在IO线程来执行,主线程继续执行下面的任务,在IO线程完成操作后会带着数据通知主线程发起回调。

事件循环

这是Node的执行模型,正是这种模型使得回调函数非常普遍。
在进程启动时,Node便会创建一个类似while(true)的循环,执行每次循环的过程就是判断有没有待处理的事件,如果有,就取出事件及其相关的回调并执行他们,然后进入下一个循环。如果不再有事件处理,就退出进程。

观察者

在每个循环中,怎么判断是否有事件需要处理呢?这里就要引入观察者了。每个事件循环中都有一个或多个观察者,而判断是否有事件要处理的过程就是向这些观察者询问是否有要处理的事件。
事件循环是一个典型的生产者/消费者模型,异步IO,网络请求等是事件的生产者,源源不断的为Node提供不同类型的事件,这些事件被传递到观察者那里,事件循环则从观察者那里取出事件并处理。

请求对象

对于Node中的异步IO调用而言,回调函数不由开发者来调用,从JS发起调用到IO操作完成,存在一个中间产物,叫请求对象。
在JS发起调用后,JS调用Node的核心模块,核心模块调用C++内建模块,內建模块通过libuv判断平台并进行系统调用。在进行系统调用时,从JS层传入的方法和参数都被封装在一个请求对象中,请求对象被放在线程池中等待执行。JS立即返回继续下面的操作。

执行回调

在线程可用时,线程会取出请求对象来执行IO操作,执行完后将结果放在请求对象中,并归还线程。
在事件循环中,IO观察者会不断的找到线程池中已经完成的请求对象,从中取出回调函数和数据并执行。

流程图

这里写图片描述

非IO的异步API

定时器

setTimeout()和setInterval()
这两个方法实现原理与异步IO相似,只不过不用线程池的参与。
使用它们创建的定时器会被放入定时器观察者中,每次事件循环执行时会从观察者中取出并判断是否超过定时时间,超过就形成一个事件,回调立即执行。
所以,和浏览器中一样,这个并不精确。

process.nextTick()

有时我们想要立即异步执行一个任务,可能会使用延时为0的定时器,但是这样开销很大。我们可以换而使用这个,这个会将传入的回调放入队列中,下一轮Tick(事件循环)中取出执行。

process.nextTick(function(){console.log("nextTick");});
console.log("thisTick");

setImmediate()

这个函数表现上与process.nextTick()相同,但是还是有细微的区别
当setImmediate()遇上process.nextTick()时,process.nextTick()的优先级高于setImmediate(),这里是因为事件循环对于观察者的检查是有顺序的,process.nextTick()属于idle观察者,setImmediate()属于check观察者。
idle观察者优于IO观察者优于check观察者。
而且,对于process.nextTick()的回调函数,是保存在一个数组中的,当有多个时,会在下一个Tick全部执行完,而setImmediate()的回调函数们在一个链表中,每轮Tick只执行一个。这样设计是为了防止一次循环持续过久,CPU过多占用。(这个特性新版本好像取消了,也是一次循环执行完,可以用下面的例子测试下)。

process.nextTick(function () {   
    console.log('nextTick执行1'); 
}); 
process.nextTick(function () {
    console.log('nextTick执行2'); 
}); 
setImmediate(function () {   
    console.log('setImmediate执行1');   
    process.nextTick(function () {     
        console.log('势入');   
    }); 
}); 
setImmediate(function () {   
    console.log('setImmediate执行2'); 
}); 
console.log('正常执行'); 

事件驱动与服务器

网络IO事件也同样的应用到了异步IO。网络上的请求都会交给IO观察者来处理。
经典的服务器有下面几种:
同步式
每进程每请求
每线程每请求
上面的模型都有在大量请求下性能下降的问题。
Node通过事件驱动来处理请求,每个请求不必创建新的线程,开销小。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 让I/O与CPU计算并行 Node 在*nix平台,通过线程池实现(主线程和I/O线程),在windows下使用I...
    wmtcore阅读 356评论 0 0
  • 参考:IOCP原理Philip Roberts: Help, I’m stuck in an event-loop...
    mary_s阅读 2,239评论 1 8
  • 设计高性能Web服务器的要点在于非阻塞I/O和事件驱动 Node最大的特点是异步式I/O(非阻塞I/O)与事件紧密...
    JunChow520阅读 2,025评论 0 0
  • 之前介绍了Node.js的事件机制, 也许读者对此尚会觉得意犹未尽,因为仅仅只是简单的事件机制,并不能道尽Node...
    七寸知架构阅读 1,896评论 1 50
  • Node的异步I/O 我们为什么需要异步I/O? 用户体验服务器端如果基于同步执行的,随着应用复杂性的增加,响应的...
    俗三疯阅读 497评论 0 0