Nodejs异步IO初探

224 阅读3分钟

这是我参与12月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境,其有以下几个关键词,事件驱动、异步io、高效、轻量。

什么是异步IO

在计算机硬件中,cpu的速度远远大于硬盘、网络的io,在一个线程中,cpu执行速度极快,但是当这个线程有访问硬盘、网络调用等io操作时,正常情况cpu就需要等待io操作完成后才能执行后续的代码,这种情况叫同步io。

如果这个线程执行的工作是为许多客户提供服务,那么一个io调用会影响所有工作的执行,所以有一种办法是为每个用户提供一个独立的线程/进程,但是当用户数量较多,cpu切换线程的开销会极速上升,导致执行效率下降。

还有另外一种方案就是异步io,异步io即非堵塞类型的io api;当代码执行一个耗时的io操作,线程只发出io指令,不等待io结果,可以执行其它的代码。io结果返回时,再通知cpu执行后续的操作。

如何实现异步IO

通常是通过消息队列来实现。主线程不断重复从消息队列中读取任务、执行任务这一过程。当执行的任务中存在io操作,则发出io操作的请求,然后结束掉这个任务,执行后续的任务。后续io操作处理完成,消息队列会push一条io处理完成的任务,处理该任务即可得到io处理的结果。

所以异步io模型可以大大提高系统的多任务处理能力,即高并发能力;当然高并发并不是仅靠异步io就可以实现,同时还需要事件循环、单线程等特性共同作用,此处不是我们研究的重点,我们先按下不表。

异步IO的执行流程

  1. 发起io调用,js调用node核心模块,将参数和回调作为入参
  2. node将入参封装成请求对象推入io线程池去执行
  3. js线程继续执行其它的任务
  4. io操作完成后会将结果和请求一块保存下来,一块送入任务队列中
  5. js线程处理到任务时,会把任务中的回调函数拿出来执行,把io结果作为入参传入,从而完成回调

Nodejs优缺点

从以上可以得知,nodejs适合做一些io密集型的应用,比如聊天室、小文件批量处理等等。

但是对于cpu密集型应用,nodejs就不那么适合了,因为nodejs执行的任务大部分都在主线程,但一个任务执行的工作量很大,需要cpu进行长时间的操作才能解决,那么它势必影响到后续任务的执行,导致效率降低。

所以我们要清楚nodejs的优势及劣势,这样在制定方案才能心中有数。