1. 概述
reactor是处理网络高并发I/O中的经典模式,Redis、Nginx、Netty等知名软件都采用该模式
核心组件为Event, Demultiplexer和Event Handler。
reactor模型为:

reactor模型主要应用在异步IO场景:

2. reactor解决什么问题
解决有限资源和无限请求之间的问题,在网络编程中,socket端口是系统有限资源。一台服务器开启socket之后,比如80,则该端口是有限的,因为只有一个。而所有的网络I/O请求,都会进入该端口,而网络请求就是无限的,任意一个网络请求都会向80端口通讯

如处理高并发的I/O请求?reactor应运而生

3. 发展历史
1. 单线程模式
最最原始的网络编程思路就是服务器就是单线程处理,在一些讲解socket编程的例子中偶尔会见到。
用一个while循环,不断监听端口是否有新的套接字连接,如果有,那么就调用一个处理函数处理,类似:
while(true){ conn = accept(); handle(conn) }
问题:
太慢
2. 多线程模式
每个客户端一个线程,早期的tomcat就采用该模式
while(true){ conn = accept(); new thread(conn); }
问题:
处理不了高并发
- 一个链接一个线程,资源要求太高
- 线程的反复创建-销毁很耗时
3. reactor模式
reactor针对前面的症结,用以下方式解决问题:
- 启用异步I/O处理机制
- 启用线程池执行处理耗时数据
- 把accept消息和数据IO分离
具体模型为:

详细方案为:
- Reactor 对象通过 Demultiplexer (如select,epoll等) 监听事件,收到事件后通过 dispatch 进行分发,具体分发给 Acceptor 对象还是 Handler 对象,还要看收到的事件类型;
- 如果是连接建立的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法 获取连接,并创建一个 Handler 对象来处理后续的响应事件;
- 如果不是连接建立事件, 则交由当前连接对应的 Handler 对象来进行响应;
- Handler 对象通过 read 读取到数据后,会将数据发给子线程里的 Processor 对象进行业务处理;
- 子线程里的 Processor 对象就进行业务处理,处理完后,将结果发给主线程中的 Handler 对象,接着由 Handler 通过 send 方法将响应结果发送给 client;
4. 多reactor模式
单 Reactor的模式还有个问题,因为一个 Reactor 对象承担所有事件的监听和响应,而且只在主线程中运行,在面对瞬间高并发的场景时,容易成为性能的瓶颈的地方。

详细方案为:
- 主线程中的 MainReactor 对象通过 select 监控连接建立事件,收到事件后通过 Acceptor 对象中的 accept 获取连接,将新的连接分配给某个子SubReactor
- 子 SubReactor 对象将 MainReactor 对象分配的连接加入 select 继续进行监听,并创建一个 Handler 用于处理连接的响应事件。
- 如果有新的事件发生时,SubReactor 对象会调用当前连接对应的 Handler 对象来进行响应。
- Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程。
和Observer模式的区别
基本上,reactor的核心流程为注册handler,监听消息和分发消息。和另一种设计模式Oberser有类似之处。
二者的大致流程都为订阅Event,分发Event,处理Event
Reactor:

Obersver:

但二者有本质的不同:
- 应用场景不同,reactor往往用于处理IO,而Oberser往往用于各模块间同步状态
- reactor涉及异步逻辑,有独立线程用于监听和分发事件,事件的执行往往用线程处理,整个模型突出异步无阻塞。而Observer则不强调异步
版权说明
本文引用图片大部分来自网络,若有侵权,请联系作者立即删除,致谢前辈们在网络提供的资料和图片!
发表回复