1 前言
程序员的进阶之路上,不可避免的是对一些源码的学习,一些好的设计我们应该吸收到自己的代码,一些经典的设计就会形成设计模式。
2 概念
Reactor模式又被称为反应器模式,是一种为处理服务请求并发,提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序。
Netty 的线程模型就是基于IO多路复用技术构建的,使用了异步驱动的Reactor 模式,可以很好的支持成百上千的 SocketChannel 连接。并且读写都是非阻塞的,可以充分提升运行效率 ,避免了阻塞式IO线程挂起的问题, 同时可以使一个线程支持对多个SocketChannel的读写操作, 从根本上解决了传统阻塞IO的一线程(进程)处理一连接的弊端。
Reactor是一种事件驱动机制,与普通函数调用的不同之处在于:
应用程序不是主动的调用某个API完成处理,应用程序需要提供相应的事件并注册到Reactor上,如果相应的事件发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”,从而执行对应的处理逻辑。
3 为什么会使用Reactor模式
至于为什么会使用Reactor模式,那就不得不提一下多线程IO的致命缺陷,首先,介绍一下什么是多线程IO模式,多线程IO模式就是在一个无限循环中监听来自客户端的Sockect连接,如果有就会新建一个线程,去处理读写任务。这样的话就是一个连接对应一个线程,这样虽然可以在一定程度上解决并发问题,但是系统在每次建立连接都需要创建一个线程,对系统资源要求极高,当并发过大,系统是无法承受巨大的压力,线程的创建和销毁都是需要消耗资源的。然后基于事件驱动的Reactor模式,正好可以控制线程的数量,让同一个线程可以处理多个连接。
4 Reactor 模式的分类
- 单线程Reactor
在单个线程内,通过不同的事件触发Reactor调度不同的处理器,达到一个线程处理多个连接
特点:
其中一个handler 阻塞,所有连接都会被阻塞,线程被阻塞后,系统也不能去接受新的连接。因此
- 多线程Reactor
多线程模型将监听独立出来,保证系统可以正常建立连接,借助线程池优化事件处理,让串行处理,变为并行处理
- 主从多线程Reactor
此模式将Reactor分为两部分,BossReactor负责监听accept新连接,然后将建立的socket通过多路复用器(Acceptor)分派给WorkReactor。WorkReactor负责多路分离已连接的socket,读写网络数据;业务处理功能,其交给worker线程池完成。通常,BossReactor线程数量为1-2个,WorkReactor个数上一般为CPU个数的二倍或者与CPU个数相同。
Netty 支持多种模式的Reactor
5 Reactor 模式的优缺点
5.1. 优点
1)响应速度快,基于事件驱动,尽可能避免阻塞(Reactor模式依然是同步);
2)借助线程池,优化线程/进程的切换创建开销;
3)高可复用性,Reactor模式与具体事件处理逻辑无关,具有很高的复用性;
5.2. 缺点
1) Reactor模式在IO读写数据时,使用同一个线程处理多个连接的读写,当某些读写的数据过大时,容易影响其他连接的读写效率。所以Reactor模式并不是在所有情况下都适用的,它更适用于处理小而多的数据传输。网络传输的数据过大时,采用传统的一线程处理一连接更适用。
2)Reactor模式需要底层的Synchronous Event Demultiplexer(IO多路复用技术)支持,比如Java中的Selector支持,linux系统的select、poll、epoll支持。
3)Reactor模式,相对比较复杂,因而具有一定的学习门槛。