阅读深入浅出Node.js
1.作系统内对于I/O只有两种方式:阻塞与非阻塞
阻塞I/O的一个特点是调用之后一定要到系统内核层面所有操作完成后,调用才结束。非阻塞I/O调用之后立即返回。
但非阻塞I/O也存在一些问题。由于完整的I/O并没有完成,立即返回的并不是业务层期望的数据,而仅仅是当前调用的状态。为了获取完整的数据,应用程序需要重复调用I/O操作来确认是否完成。这种重复调用判断操作是否完成的技术叫做轮询。
我们期望的完美的异步I/O应该是应用程序发起非阻塞调用,无需通过遍历或者事件唤醒等方式轮询,可以直接处理下一个任务,只需要在I/O完成后通过信号或回调将数据传递给应用程序即可。
现实中异步I/O,我们将场景限定在了单线程的状况下。通过部分线程进行阻塞I/O或者非阻塞I/O加轮询技术来完成数据获取,让一个线程进行计算处理,通过线程之间的通信将I/O得到的数据进行传递,姐实现了异步I/O。
2.Node自身的执行模型————事件循环
在进程启动时,Node会创建一个类似于while(true)的循环,一次循环体的过程我们称为Tick。每个Tick的过程就是查看是否有事件待处理,如果有,就去取出事件及相关的回调函数。如果存在关联的回调函数,就执行它们。然后进入下个循环,如果不再有事件处理,就退出进程。
每个事件循环中有一个或者多个观察者,而判断是否有事件要处理的过程就是向这些观察者询问是否有要处理的事件。
3.process.nextTick()
在未了解process.nextTick()之前,立即异步执行一个任务,会使用setTimeout
setTimeout(() => {
},0)
由于事件循环自身的特点,定时器的精确度不够。而事实上,采用定时器需要动用红黑树,创建定时器对象和迭代等操作,setTimeout(fn,0)的方式比较浪费性能。process.nextTick()方法的操作相对比较轻量。
4.Node的优势与缺点
Node带来的最大特性就是基于事件驱动的非阻塞I/O模型。非阻塞I/O可以使CPU与I/O并不互相依赖等待,让资源得到更好的利用。
Node为了解决编程模型中阻塞I/O的性能的问题,采用了单线程模型。这导致Node更像一个处理I/O密集问题的能手,而CPU密集型则成为Node的缺点
5.V8的内存限制
在Node中通过JavaScript使用内存时就会发现只能使用部分内存。在这样的限制下,将会导致Node无法直接操作大内存对象。造成这个问题的主要原因在于Node基于V8构建,所以在Node中使用JavaScript对象基本上都是通过V8自己的方式来进行分配和管理的。