从时间碎片角度理解阻塞IO模型及非阻塞模型

阻塞模型限制了服务器的并发处理能力(伸缩性或同时处理的客户端链接数)

传统的网络服务器只支持阻塞模型,该模型下,针对每一个客户端链接,服务器都必须建立一个线程来处理这个链接上的请求,服务器必须维持着这些线程直到线程中的处理工做结束。缓存

服务器上所能建立的线程数量是有限的,WHY?服务器

  • 进程上下文切换是耗时的过程
  • 建立的进程自己占用资源,好比每一个进程或线程占用必定容量的内存
  • 等待数据准备和内核缓存复制,致使IO阻塞,占用着线程

因此当链接到服务器上的客户端的数量很大时,把服务器上所能建立的线程都占据了时,服务器就没法接受更多的链接了。这限制了服务器处理请求的伸缩性。网络

并不是全部客户端都是持续活跃的

存在这样一个事实,就是虽然链接到服务器上的客户端不少,但并不是全部客户端都是持续活跃着的。它们占据着阻塞式服务器的线程资源——即便它们处于非工做状态。这些线程占据了资源,却不工做。多线程

这会形成什么现象呢?
就是线程时间的碎片化——一个线程大部分时间是在等待IO操做的结果。并发

为了让服务器能接受更多客户端的链接,非阻塞模型就出现了。异步

如何提高服务器的并发处理能力?

消灭碎片化时间,能够提高服务器的并发处理能力。操作系统

如何消灭碎片化时间? 让线程分工协做各司其职,是一个很好的手段。
原来的阻塞模型下,一个线程要干全部的事情。分工协做机制下,一部分线程专门用于接受客户端的链接、一部分专门用于获取请求的数据、一部分专门执行计算工做、还有一部分线程专门用于响应客户端。
接受客户端链接的线程在接收到客户端链接后,当即把链接交给后续工序的线程处理,而它本身则继续接受下一个链接。如此类推,各个线程无须等待,不存在碎片化时间,全负荷工做。
这样一来,总体上须要的较少的线程,就能够完成之前须要较多线程才能达到的工做时间了。线程

阻塞模型下的实现方式

在阻塞模型下,利用异步处理的方式对线程进行分工协做。接收请求的线程能够满负荷工做,但处理IO操做的线程仍然是阻塞着的,仍然存在线程工做不饱和的现象。进程

非阻塞模型完全消灭线程工做不饱和

非阻塞模型下,IO操做再也不是阻塞的了,而是当即返回。这样的话,处理IO操做的线程,能够在空闲时对全部请求进行轮询,以便判断哪些IO操做已完成。好比判断某个请求是否能够进行“写”操做,若是还不能够,无须等待,继续判断下一个请求是否能够进行“读”操做,若是能够则当即读取数据,而后把数据转交给专职计算的线程。这样就让线程工做不饱和现象消失了。内存

这是所谓的“同步非阻塞”。

轮询的耗时如何消灭?

这就要请出“IO复用”这尊大神了。

IO复用模型下,线程一次性从操做系统那儿得到一批能够进行IO操做的请求,处理完毕后,再此得到新的一批。线程无须与操做系统交互屡次以便轮询每一个请求的状态,而是与操做系统交互一次便可得到批量信息。效率进一步提升啦。

相关文章
相关标签/搜索