服务器模型——从单线程阻塞到多线程非阻塞(下)

前言的前言

服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各类场景有的放矢。该系列分红三部分:服务器

  • 单线程/多线程阻塞I/O模型
  • 单线程非阻塞I/O模型
  • 多线程非阻塞I/O模型,Reactor及其改进

前言

这里探讨的服务器模型主要指的是服务器端对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模型已经大大提升了机器的效率,而在多核的机器上能够经过多线程继续提升机器效率。最朴实、最天然的作法就是将客户端链接按组分配给若干线程,每一个线程负责处理对应组内的链接。如图所示,有4个客户端访问服务器,服务器将套接字1和套接字2交由线程1管理,而线程2则管理套接字3和套接字4,经过事件检测及非阻塞读写就可让每一个线程都能高效处理。分布式

这里写图片描述

最经典的多线程非阻塞I/O模型方式是Reactor模式。首先看单线程下的Reactor,Reactor将服务器端的整个处理过程分红若干个事件,例如分为接收事件、读事件、写事件、执行事件等。Reactor经过事件检测机制将这些事件分发给不一样处理器去处理。如图所示,若干客户端链接访问服务器端,Reactor负责检测各类事件并分发处处理器,这些处理器包括接收链接的accept处理器、读数据的read处理器、写数据的write处理器以及执行逻辑的process处理器。在整个过程当中只要有待处理的事件存在,便可以让Reactor线程不断往下执行,而不会阻塞在某处,因此处理效率很高。高并发

基于单线程Reactor模型,根据实际使用场景,把它改进成多线程模式。常见的有两种方式:一种是在耗时的process处理器中引入多线程,如使用线程池;另外一种是直接使用多个Reactor实例,每一个Reactor实例对应一个线程。学习

这里写图片描述

Reactor模式的一种改进方式如图所示。其总体结构基本上与单线程的Reactor相似,只是引入了一个线程池。因为对链接的接收、对数据的读取和对数据的写入等操做基本上都耗时较少,所以把它们都放到Reactor线程中处理。然而,对于逻辑处理可能比较耗时的工做,能够在process处理器中引入线程池,process处理器本身不执行任务,而是交给线程池,从而在Reactor线程中避免了耗时的操做。将耗时的操做转移到线程池中后,尽管Reactor只有一个线程,它也能保证Reactor的高效。.net

这里写图片描述

Reactor模式的另外一种改进方式如图所示。其中有多个Reactor实例,每一个Reactor实例对应一个线程。由于接收事件是相对于服务器端而言的,因此客户端的链接接收工做统一由一个accept处理器负责,accept处理器会将接收的客户端链接均匀分配给全部Reactor实例,每一个Reactor实例负责处理分配到该Reactor上的客户端链接,包括链接的读数据、写数据和逻辑处理。这就是多Reactor实例的原理。线程

多线程非阻塞I/O模式让服务器端处理能力获得很大提升,它充分利用机器的CPU,适合用于处理高并发的场景,但它也让程序更复杂,更容易出现问题。设计

这里写图片描述

=============广告时间===============

公众号的菜单已分为“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有须要的朋友能够购买。感谢各位朋友。

为何写《Tomcat内核设计剖析》

=========================

欢迎关注:

这里写图片描述
相关文章
相关标签/搜索