Reactor模型
解决的问题:
- NIO-API复杂,开发难度大;
Netty:
- 是对NIO的API进行封装;
- 性能高,吞吐量高,延迟低,减少资源消耗,减少不必需要的内存复制;
- 基于主从Reactor多线程模型
传统阻塞IO架构:
Reactor模型
- ServiceHandler将传入的多个请求,根据事件,分发给相应的处理线程;
- ServiceHandler:即一个Reactor
- 基于Dispatcher分发模式;
- 使用了IO复用监听事件;
分类:
- 单Reactor单线程;
- 单Reactor多线程;
- 主从Reactor多线程;
单Reactor单线程
Reactor,Handler都是同一个线程;(单层架构,性能差)
- Reactor通过
Selecotr.select
:监听多路连接请求; - 收到连接事件后,通过Acceptror处理连接请求;
- 收到读写事件,通过Handler处理业务;
单Reactor多线程
分为:主线程Reactor,业务处理线程池;(两层架构)
- Reactor中
Selecotr.select
方法,进行轮询; - 连接请求:通过
serverSocketChannel.accept()
方法建立连接,并创建对应的Handler; - 读写请求:调用此连接对应的Handler进行相应,Handler只负责响应,不做业务处理;
- Handler读取事件数据,启动一个独立的
Worker线程
,进行业务处理,结果返回Handler - Handler收到结果,将响应返回给Client;
优点:充分利用多核CPU,并发处理能力;
缺点:在高并发场景,由于主线程处理所有的连接请求,读写请求,容易出现瓶颈;
主从Reactor多线程
这个图不全,这里的SubReactor
子线程,是可以有多个的;
在netty中MainReactor
也是有多个的;
在单Reactor基础上:(三层架构)
-
MainReactor
:只需要处理连接请求,将读写请求交由子线程SubReactor
处理; - 多个Reactor子线程
SubReactor
:分担了MainReactor
的读写请求; -
MainReactor
建立连接完成的Channle会加入一个连接队列,SubReactor
通过Selecotr.select
轮询监听连接的事件; - 有读写事件发生时:
SubReactor
会调用相应的Handler进行处理; - Handler读取数据,从线程池中,调用独立work线程,处理业务,返回结果给Handler;
- Handler收到结果,send给Client;
优点:
(1)父线程与子线程的数据交互简单职责明确;
(2)父线程与子线程的数据交互简单,MainReactor
主线程只需要把新连接传给子线程,子线程无需返回数据。
缺点:编程复杂度较高;