reactor模型

特点

  1. 事件驱动
  2. 可以处理一个或多个输入源
  3. 通过多路复用将请求的事件分发给对应的处理器处理

根据大神Doug Lea 在 《Scalable IO in Java 》中的介绍,Reacotr模型主要分为三个角色

  1. Reactor:把IO事件分配给对应的handler处理
  2. Acceptor:处理客户端连接事件
  3. Handler:处理非阻塞的任务

传统io阻塞模型:来一个请求,开启一个线程,如果线程读取不到数据,那么就会一直阻塞

缺点:大量线程耗费服务器性能,线程阻塞也是对资源的浪费

针对io阻塞模型的解决方案

  1. 使用池化思想,避免线程的频繁开启与销毁,减小性能开销
  2. io复用模型,多个连接对象使用一个阻塞对象,不断遍历连接对象,有数据来了,就通知程序实现业务逻辑。

根据线程池的数量和reactor的数量分为三种reactor模型:

  1. 单Reactor单线程模型
  2. 单Reactor多线程模型
  3. 多Reactor多线程模型

单Reactor单线程模型 这种模型在Reactor中处理事件,并分发事件,如果是连接事件交给acceptor处理,如果是读写事件和业务处理就交给handler处理,但始终只有一个线程执行所有的事情

img

该线程模型的不足

  1. 仅用一个线程处理请求,对于多核资源机器来说是有点浪费的
  2. 当处理读写任务的线程负载过高后,处理速度下降,事件会堆积,严重的会超时,可能导致客户端重新发送请求,性能越来越差
  3. 单线程也会有可靠性的问题

针对上面的种种不足,就有了下面的线程模型

单Reactor多线程模型 这种模型和第一种模型到的主要区别是把业务处理从之前的单一线程脱离出来,换成线程池处理,也就是Reactor线程只处理连接事件和读写事件,业务处理交给线程池处理,充分利用多核机器的资源、提高性能并且增加可靠性

img

该线程模型的不足

Reactor线程承担所有的事件,例如监听和响应,高并发场景下单线程存在性能问题

多Reactor多线程模型 这种模型下和第二种模型相比是把Reactor线程拆分了mainReactor和subReactor两个部分,mainReactor只处理连接事件,读写事件交给subReactor来处理。业务逻辑还是由线程池来处理

img

mainRactor只处理连接事件,用一个线程来处理就好。处理读写事件的subReactor个数一般和CPU数量相等,一个subReactor对应一个线程,业务逻辑由线程池处理

这种模型使各个模块职责单一,降低耦合度,性能和稳定性都有提高

这种模型在许多项目中广泛应用,比如Netty的主从线程模型等

Reactor三种模式形象比喻 餐厅一般有接待员和服务员,接待员负责在门口接待顾客,服务员负责全程服务顾客 Reactor的三种线程模型可以用接待员和服务员类比

  1. 单Reactor单线程模型:接待员和服务员是同一个人,一直为顾客服务。客流量较少适合
  2. 单Reactor多线程模型:一个接待员,多个服务员。客流量大,一个人忙不过来,由专门的接待员在门口接待顾客,然后安排好桌子后,由一个服务员一直服务,一般每个服务员负责一片中的几张桌子
  3. 多Reactor多线程模型:多个接待员,多个服务员。这种就是客流量太大了,一个接待员忙不过来了