开始正题,reactor 模式nodejs关于异步的本质,以及隐藏在此模式背后的故事。如单进程单线程的架构、非阻塞IO。最后看下整个nodejs平台。
IO很慢,相比于cpu的处理速度来说,在非密集型计算的应用场景下,IO是一个拖慢速度的瓶颈。当然,现在正火的深度学习可以一次跑上几个月。。。。这种计算密集型的应用场景下除外。
一个传统的阻塞型io的例子,
线程池中每个线程处理一个链接,上下文切换,读写等待。。。。。性能空闲了很多。
非阻塞IO
立即返回而不是等待数据读写完毕,如果数据读写出错则返回一个预定义的常量。类似于c语言中回调函数。
实现非阻塞IO的方法一:busy-waiting+polling loop
resources = [socketA,socketB,pipeA];
while(!resources.isEmpty()) {
for(i = 0; i < resources.length; i++) {
resource = resources[i];
//try to read
var data = resource.read();
if(data === NO_DATA_AVAILABLE)
//there is no data to read at the moment
continue;
if(data === RESOURCE_CLOSED)
//the resource was closed,remove it from the list
resources.remove(i);
else
//some data was received,process it
consumeData(data);
}
}
实现起来很简单,缺点也很明显,cpu占用率过高,轮询的方式代价很大,但是也简单的说明的一个异步io的实现方式。
实现非阻塞IO的方法二:event notify/event loop
socketA,pipeB;
watchedList.add(socketA,FOR_READ); //[1]
watchedList.add(pipeB,FOR_READ);
while(events = demultiplexer.watch(watchedList)) { //[2]
//event loop
foreach(event in events) { //[3]
//This read will never block and will always return data
data = event.resource.read();
if(data === RESOURCE_CLOSED)
//the resource was closed,remove it from the watched list
demultiplexer.unwatch(event.resource);
else
//some actual data was received,process it
consumeData(data);
}
}
这种方式利用率高多了,如图
reactor 模式
终于开始正题了。。
nodejs以每一个 模块都很小 ,每个模块都work的很好的思想,并把这种思想作到了极致。
使用npm作为模块的管理,把可重用性以及可维护性做到极致。解决了dependancy hell。
一个小的模块还有如下优点:
容易理解与使用、测试与维护更加简便、更加容易传播。
每个人都可以传播自己的代码,省去的重复造轮子的工作。相比于cpp。。。。轮子轮子再造个轮子。
额。。。回来重新说reactor模式
其实reactor模式在上面已经说过了,上面的event notify,也叫event loop的一种特例。
看图说话
1。 发个req,然后就返回去执行下一条指令了
2。 event Demultiplexer 等待一组IO操作完成后。。。也就是等event queue把手头的活做完,把req加入event队列
3. event queue 把所有的event一股脑丢尽event loop,执行去吧
4 执行完的任务返回给application,通过handle一一对应。
5a 还有要做的事情啊,啊?这么急?先给你做好了
5b 做完啦,结果给你吧
6 没有事情可以做,我先休息一会,event loop休息去了,有活再叫我
reactor模式到底是个啥?
有处于观察期的资源可用时,这时把资源和操作对应成event,把event分发给各自相关handle。
nodejs用的非阻塞io引擎:libuv
libuv兼容了win,*nix,mac的底层异步读写操作。c语言实现的跨平台的library。
libuv实现了reactor模式,提供api来创建event loop,管理event queue,运行异步io操作,对其他类型的任务queue。
之前说过要show整个nodejs的平台,还需要几个东西。。。。。
首先libuv,v8,然后就是javascript。
看图说话
欢迎加q群243153894交流