浅谈节点异步IO和事件循环

  

  

学习节点就绕不开异步IO、异步IO又与事件循环息息相关,而关于这一块一直没有仔细去了解整理过,刚好最近在做项目的时候,有了一些思考就记录了下来,希望能尽量将这一块的知识整理清楚,如有错误,请指点轻喷~ ~

  

  

<>强,同步异步,阻塞非阻塞

  

查阅资料的时候,发现很多人都对<代码>异步和非阻塞> 行为即两者之间的关系> 状态即某一方>   

以前端请求为一个例子,下面的代码很多人都应该写过

        美元. ajax (url) .succedd(()=比;{   ……//做某事   })      

<代码>同步异步

  

如果是同步的话,那么应该是客户发起请求后,一直等到发球处理请求完成后才返回继续执行后续的逻辑,这样<代码>客户端和服务之间就保持了同步的状态>   

如果是异步的话,那么应该是客户发起请求后,<代码>立即返回>   

<代码>阻塞非阻塞

  

首先需要明白一个概念,Js是单线程,但是浏览器并不是,事实上你的请求是浏览器的另一个线程在跑。

  

如果是阻塞的话,那么<代码>该线程就会一直等到这个请求完成之后才能被释放用于其他请求>   

如果是非阻塞的话,那么<代码>该线程就可以发起请求后而不用等请求完成继续做其他事情>   

<代码>总结

  

之所以经常会混乱是因为没有说清楚讨论的是哪一部分(下面会提到),所以<代码>同步异步讨论的对象是双方,而阻塞非阻塞讨论的对象是自身>   

<强> IO和CPU

  

<代码> Io和Cpu是可以同时进行工作的

  

<代码> IO:

  

I/O(英语:输入/输出),即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。

  cpu

<代码>

  

解释计算机指令以及处理计算机软件中的数据。

  

  

IO分为<代码>磁盘IO和网络IO>   

      <李>等待数据准备(等待数据做好准备)   <李>将数据从内核拷贝到进程中(将数据从内核复制到流程)   
  

<强>节点中的磁盘Io

  

以下的讨论基于* nix系统。

  

理想的异步Io应该像上面讨论的一样,如图:

  

浅谈节点异步IO和事件循环

  

而实际上,我们的系统并不能完美的实现这样的一种调用方式,节点的异步IO,如读取文件等采用的是线程池的方式来实现,可以看的到,节点通过另外一个线程来进行IO操作,完成后再通知主线程:

  

浅谈节点异步IO和事件循环

  

而在窗下,则是利用IOCP接口来完成,IOCP从用户的角度来说确实是完美的异步调用方式,而实际也是利用内核中的线程池,其与无系统的不同在于后者的线程池是用户层提供的线程池。

  

<强>节点中的网络Io

  

在进入主题之前,我们先了解下Linux的Io模式,这里推荐大家看这篇文章,大致总结如下:

  

<代码>阻塞I/O(阻塞IO)

  

浅谈节点异步IO和事件循环

  

所以,阻塞IO的特点就是在IO执行的两个阶段都被阻止了。

  

<代码>非阻塞I/O(非阻塞IO)

  

浅谈节点异步IO和事件循环

  

当用户进程发出读操作时,如果内核中的数据还没有准备好,那么它并不会阻止用户进程,而是立刻返回一个错误。从用户进程角度讲,它发起一个读操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个错误时,它就知道数据还没有准备好,于是它可以再次发送读操作,一旦内核中的数据准备好了,并且又再次收到了用户进程的系统调用,那么它马上就将数据拷贝到了用户内存,然后返回。

浅谈节点异步IO和事件循环