图解Reactor模型
Posted 大数据记事本
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图解Reactor模型相关的知识,希望对你有一定的参考价值。
在BIO线程模型中,为了解决同步阻塞的问题,采用了多线程的方式处理并发,即经典的connection per thread,每一个连接用一个线程处理。虽然在单个线程内仍然是阻塞的,但在整体上看是可以同时处理多个连接请求的,原理图如下:
但这种方式的缺点在于资源要求太高,系统中创建线程是需要比较高的系统资源的,如果连接数太多,系统无法承受,而且,线程的反复创建和销毁也需要代价。
-
I/O多路复用:多个连接共用一个阻塞对象(即下图中的ServiceHandler),应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接,当某个连接有新的数据可以处理时,操作系统通知应用程序线程从阻塞状态返回,并将数据分发给对应的线程处理 -
基于线程池复用线程资源:不必再为每个连接创建线程,将连接完成后的业务处理任务交给线程池中的线程处理,处理完成后归还线程,同一个线程可以处理多个连接的业务,达到线程复用
在Reactor线程模型的发展过程中,出现了不同的实现方式,具体有:
单Reactor单线程
单Reactor多线程
主从Reactor多线程
1.单Reactor单线程模式 (Reactor和handler都在同一个线程中)
-
Select是IO复用模型介绍的标准网络编程API,可以实现应用程序通过一个阻塞对象监听多路连接请求 -
Reactor对象通过Select监控客户端请求事件,收到事件后通过Dispatch进行分发 -
如果是建立连接请求事件,则由Acceptor通过Accept处理连接请求,然后创建一个Handler对象处理连接完成后的后续业务 -
如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来处理业务 -
Handler会完成Read->业务处理->Send的完整业务流程
-
服务器端用一个线程通过多路复用搞定所有的IO操作,包括连接、读、写等,但是如果客户端连接数较多,将无法支撑,比如处理一个客户端的业务时,别的客户端的业务请求只能阻塞等待 -
单线程无法发挥多核CPU的性能
-
Reactor对象通过select监控客户端请求事件,收到事件后,通过dispatcher进行分发 -
如果是建立连接的请求,则由Acceptor通过accept处理连接请求,然后创建一个Handler对象处理完成连接后的各种事件 -
如果不是连接请求,则由Reactor分发调用连接对应的handler进行处理 -
handler只负责响应事件,不做具体的业务处理,通过read读取数据后,会分发给后面的worker线程池的某个线程处理业务 -
worker线程池会分发独立的线程完成真正的业务,并将结果返回给handler -
handler收到响应的结果后,再通过send将结果返回给client
优点:
多线程可以充分利用多核CPU的处理能力
采用线程池复用线程,减少创建和销毁线程带来的性能开销
缺点:
reactor处理所有事件的监听和响应,在单线程运行,高并发场景下容易出现性能瓶颈
多线程数据共享和访问比较复杂
3.主从Reactor多线程
方案说明:
Reactor主线程MainReactor对象通过select监听连接事件,收到事件后,通过Acceptor处理连接事件
当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor
SubReactor将连接加入到连接队列进行监听,并创建handler进行各种事件处理
当有新事件发生时,SubReactor就会调用对应的handler进行处理
handler通过Read读取数据,分发给后面的worker线程处理
worker线程池会分配独立的worker线程进行业务处理,并返回结果
handler收到响应的结果后,再通过send将结果返回给client
MainReactor主线程可以关联多个SubReactor子线程
优点:
主线程与子线程的数据交互简单职责明确,主线程只需要接收新连接,子线程完成后续的业务处理
可以通过扩展多个Reactor子线程的方式来减小单个子线程的压力,提高并发处理能力
Netty就是在主从Reactor多线程模型的基础上进行了一定的改进,同时,Kafka的网络架构设计也采用了这种主从Reactor多线程的模型。
以上是关于图解Reactor模型的主要内容,如果未能解决你的问题,请参考以下文章