Reactor模式是为何而来的?
我们知道Web服务最基本的流程是这样的 : 请求->解码->处理->编码->响应,
针对客户端的并发请求, 一般的服务框架设计思路都是这样的:
每次接入请求,都会指定一个线程, 去处理与客户端的通信,极大的缓解了单线程模式下, IO阻塞导致线程执行等待而无法及时
处理其他接入请求的问题, 提升了并发性能,但这种设计思路在并发量增大的时候, 又很严重的资源消耗严重, 线程过度扩张,难以
管理, 严重时可能导致内存资源耗尽, 服务器宕机, 针对这种情况, 结合线程池和任务队列的技术, 一种优化后的版本:
通过任务队列控制服务线程的规模, 线程池负责管理服务线程, 避免重复创建带来的资源消耗, 至少服务不会因为资源消耗而崩溃, 在稳定性方面要不第一
种更优秀一些, 但是当请求量很大, 任务队列满负荷, 会出现新建任务拒绝, 而且一旦服务线程中的阻塞时间太长, 线程池空闲线程总是处于短缺状态, 已加
入任务队列的连接很可能会出现超时的情况, 所以依然不尽如人意!
针对以上种种问题, 计算机领域的大神们设计了Reactor模式, 下面分析该模式的两种版本:初级版和高级版
1、初级版 - 单线程版本
Reactor是很典型的IO复用机制的应用, 将多个IO事件(读事件、写事件)阻塞在类似select这样的系统调用上, 当某个事件
就绪后, 由OS负责通知对应的事件处理器,这样就避免了多个线程都处于阻塞状态, 仅阻塞在select线程中, 提高了处理效率
,避免线程等资源一直处于空闲等待,提升了服务的吞吐量, 这种设计方案一般是理论版本, 很多通信框架实际都不这样实现,
因为实际情况是如果Reactor作为select单线程既负责处理接入事件, 又要负责处理IO通信事件,运行效率会非常低, 不能完
全发挥Reactor高效并发处理优势,所以像诸如netty这样的通信框架,一般会用高版本的Reactor模式实现其核心处理框架!
2、高级版 - 多线程版本
mainReactor作为单线程负责处理接入事件, 一旦有接入请求进来, 则交给Acceptor处理, Acceptor接受连接后, 将代表连接的
套接字句柄向subReactor(多线程)注册, 接下来的IO通信事件完全由subReactor处理, 这种设计将连接接入和IO操作分开处理,
提高了处理效率, 有更好的并发性能!
以上图片出处 : Scalable IO in Java Netty5.0架构剖析和源码解读