Reactor模型与Proactor模型

3,769 阅读5分钟

(本文是站在Java角度讲述这两个模型,所以只谈线程)。 在介绍这两种模型之前先介绍一下在I/O场景下同步、异步、阻塞、非阻塞的概念。 我们都知道我们的程序是运行在操作系统上的,我们程序和服务器硬件之间隔着个操作系统,一般情况下我们的服务器都是linux系统,为了安全考虑linux系统又分了:用户态和内核态

I/O操作得经历两个过程: 1、读存储设备数据到内核缓存 2、从内核缓存读数据到用户空间

1操作比2操作慢的多,因为去磁盘寻址啊等操作比较慢。

然后我们平日里针对I/O场景下说的阻塞I/O、非阻塞I/O指的就是1操作是否阻塞,也就是会立即返回一个状态值,还是会等待存储设备数据读取到内核缓存后在返回所需的数据。

而平日里说的同步I/O、异步I/O指的是2操作是否会阻塞。

Reactor模型

它是同步非阻塞模型。也称为Dispatcher模型。想想如果每一个连接过来我们都得建一个线程来处理这个连接,那连接一多线程不得爆满,那可能有人说上线程池,对线程池肯定是要上的。但这只能解决线程数的问题,但还有一个问题就是资源利用率的问题,当连接没断开的时候,当这个连接暂时没请求的时候你的线程是不是得阻塞着等着请求呀,那线程等于还是被人占用了,别的连接有请求的时候也用不到这个线程,资源的浪费啊,性能低啊。

那如何解决这个问题呢?

当然是等连接有请求的时候线程再上去处理。那这个事情得找个“人”来做,咱们业务线程就处理业务,就是得有个“人”来管理所有的连接,他发现哪个连接有请求了就分配业务线程来处理。

这就叫Reactor模型。上面说的那个"人"我们称为reactor,中文翻译时反应堆的意思,也就是他就是那个监视的人,如果有情况来了他就有所反应,分发任务给业务线程处理。

可以有单Reactor单线程,单Reactor多线程,多Reactor多线程 ###单Reactor单线程

单Reactor单线程

select会一直监听着事件,事件来了之后给dispatch分发,如果建立请求的事件则分配的acceptor,由acceptor创建一个handler来处理后续的业务,如果不是建立请求的事件则分配个之前对应的handler来处理后续业务

这个情况的优点就是简单。。。没有多线程共享资源争抢导致的问题。缺点就是就单线程,浪费了多CPU,并且同一时刻只有一个handler能处理,其他的得等着。

听起来好像没啥用啊这样,是的绝大部分场景不适合,但是redis就是这样用的。因为它处理业务够快。所以这种适合在业务处理极快的情况下使用。 ###单Reactor多线程

单Reactor多线程
当业务处理不快就上多线程咯。

这个模式和上面的区别就在于具体业务实现不由handler处理的,handler只负责read数据,将数据给业务线程,然后业务线程处理完毕之后返回结果给handler,由handler send给客户端 。 这个模式的优点就是可以充分利用CPU,适合业务处理不快的情况。缺点就是多线程之间共享资源的争抢产生的问题,并且只有一个Reactor来监听并响应,当请求量太大时,一个Reactor可能会成为性能瓶颈。 ###多Reactor多线程 所以多Reactor多线程就来啦。

多Reactor多线程
mainReactor主要用来接受连接,由连接来就给acceptor,acceptor将新的连接分配个某个subReactor,然后这个subReactor将其加入自己的监听列表,并创建一个handler来处理这个连接。之后就都由这个subReactor来select监听来响应这个连接的请求,然后dispatch给对应的handler来read,业务处理,send。mainReactor就不管啦。

所以这种方案就等于主Reactor分流了,只有新的连接由主Reactor接受,老的连接都分给了subReactor来响应。

Proactor模型

它是异步非阻塞模型。中文翻译为前摄器。。不知道啥玩意,可以称之为主动器。也就是我们不必等待I/O数据准备好也就是内核缓存已经读数据到用户空间。这一切都有内核来帮我们搞定,数据准备好了之后就通知Proactor,然后Proactor就调用相应的Handler进行业务处理。相对于Reactor省去了遍历事件通知队列selector 的代价。

Proactor模型
由initiator创建handler和proactor并通过Asynchronous Operation Processor注册到内核,然后Asynchronous Operation Processor完成I/O会通知proactor,proactor再调用对应的handler处理业务。

所以理论上Proactor的效率比Reactor高,但是linux并没有真正的实现Proactor模型,而是epoll模拟出Proactor模型。


如果错误欢迎指正!个人公众号:yes的练级攻略