Nodejs 异步I/O

139 阅读2分钟

相关概念

异步I/O与非阻塞I/O

操作系统内核对IO
  • 阻塞:应用程序需要等待IO完成才返回结果
  • 非阻塞:不带数据直接返回(返回仅仅是当前调用的状态),要获取数据需要通过文件描述符再次读取(重新判断操作是否完成:轮询)
轮询技术
  • read
  • select
  • poll
  • epoll
理想非阻塞异步IO

应用程序发起非阻塞调用,无须通过便利或事件唤醒等方式轮询,可以直接处理下一任务,只需在IO完成后通过信号或回调将数据传递给应用程序即可

现实异步IO

~nix:自定义线程池 Window:IOCP 调用异步方法,等待IO完成之后的通知,执行回调,用户无需考虑轮询
node平台提供libuv作为抽象封装层,使得所有平台兼容性的判断都有这一层来完成,保证上层node与下层自定义线程池及IOCP之间各自独立

image.jpeg

node的异步IO

关键词 单线程、事件循环、观察者和IO线程池
node异步模型的基本要素 事件循环、观察者、请求对象和IO线程池

事件循环

image.jpeg

观察者

判断是否有事件需要处理 事件循环是一个典型的生产者/消费者模型。事件被传递到对应的观察者那里,事件循环则从观察者那里取出事件并处理

请求对象

请求对象是异步IO过程中的重要中间产物,所有状态都保存在这个对象中,包括送入线程池等待执行以及IO操作完毕后的回调处理

image.jpeg

执行回调

异步IO第一步:组装好请求对象、送入IO线程池等待执行 第二步:回调通知

image.jpeg

非IO的异步API

定时器

setTimeout() setInterval()

创建定时器插入定时器观察者内部的一个红黑树中。每次Tick执行时会从红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过就形成一个事件,回调函数立即执行 问题在于:它并不精确

process.nextTick()

会将回调函数放入队列中,下一轮Tick是取出执行 ……