Reactor模型学习笔记

本文介绍了Reactor模型的基本概念,包括其在web服务中的应用及三种不同的实现方式:单线程模型、多线程模型和主从多线程模型。详细阐述了每种模型的工作原理及其优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        学习Netty的过程中,说Netty的线程模型就是基于Reactor模型的一个实现。因此,这里对Reactor模型进行了简单的学习,并进行了一些整理。

        

        在web服务中,处理web请求通常有两种体系结构,分别为:thread-based architecture(基于线程的架构)、event-driven architecture(事件驱动模型)

thread-based architecture(基于线程的架构):

        多线程并发模式:一个连接一个线程,服务器每当收到客户端的一个请求, 便开启一个独立的线程来处理。前面nio的文章中BIO的多线程实现方式就是这种。

event-driven architecture(事件驱动模型):

        事件驱动体系结构是目前比较广泛使用的一种。这种方式会定义一系列的事件处理器来响应事件的发生,并且将服务端接受连接对事件的处理分离。其中,事件是一种状态的改变。比如,tcp中socket的new incoming connection、ready for read、ready for write。

        Reactor模式和Proactor模式都是是event-driven architecture(事件驱动模型)的实现方式。

Reactor主要分为几个组件:分别是Reactor,Acceptor,Handler

        Reactor组件负责分发事件,如果是连接事件,那么交给Acceptor,如果是读写事件,那么交给Handler。

        Acceptor负责处理连接事件(获取新连接,注册到Selector上,注册读写事件,绑定Handler)。

        Handler负责处理读写事件(使用channel进行读写)。

而根据Reactor的数量和线程池的数量,又将Reactor分为三种模型:

        单线程模型(单Reactor单线程)

        多线程模型(单Reactor多线程)

        主从多线程模型(多Reactor多线程)

单线程模型(单Reactor单线程):

        Reactor内部通过selector监控事件,收到事件后通过dispatch进行分发,如果是连接建立的事件,则由Acceptor处理,Acceptor通过accept接受连接,并创建一个Handler来处理连接后续的各种事件,如果是读写事件,直接调用连接对应的Handler来处理。

        关键部分代码示例(https://www.jianshu.com/p/eb28811421e3):

        1.Reactor内部通过selector监控事件,收到事件后通过dispatch进行分发。

        2.dispatch中如果是连接建立的事件,则由Acceptor处理,如果是读写事件,直接调用连接对应的Handler来处理。

        这里需要解释一下,通过传入的key的attachment方法获取到对应的Acceptor或Handler(代码中的Processor),因为Acceptor或Handler(代码中的Processor)类都实现了Runnable接口。然后调用Acceptor或Handler的run方法,这样就可以做到事件转发了。

        3.Acceptor通过accept接受连接,并创建一个Handler(代码中的Processor)来处理连接后续的各种事件。

        上面是典型的单线程版本的Reactor实现,实例化Reactor对象的过程中,在当前多路复用器Selector上注册了OP_ACCEPT事件,当OP_ACCEPT事件发生后,Reactor通过dispatch方法执行Acceptor的run方法,Acceptor类的主要功能就是接受请求,建立连接,并将代表连接建立的SocketChannel以参数的形式构造Handle(Processor)对象。

        4.Handler(Processor)来处理对应channel的读写事件。

         Handler完成read->(decode->compute->encode)->send的业务流程。

注:

        上面的Acceptor和Handler虽然都实现了Runnable接口,但是在调用时都是直接调用的run方法,不是多线程的。

       优点:模型简单,没有多线程、进程通信、竞争的问题,全部都在一个线程中完成。

       缺点:性能问题,只有一个线程,无法完全发挥多核 CPU 的性能。Handler 在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈

       缺点:可靠性问题,线程意外终止,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障 。

多线程模型(单Reactor多线程):

        主线程中,Reactor对象通过selector监控事件,收到事件后通过dispatch进行分发,如果是连接建立事件,则由Acceptor处理,Acceptor通过accept接收连接,并创建一个Handler来处理后续事件,而Handler只负责响应事件,不进行业务操作,也就是只进行read读取数据和write写出数据,业务处理交给一个线程池进行处理

        线程池分配一个线程完成真正的业务处理,然后将响应结果交给主进程的Handler处理,Handler将结果send给client。

        单Reactor承当所有事件的监听和响应,而当我们的服务端遇到大量的客户端同时进行连接,或者在请求连接时执行一些耗时操作,比如身份认证,权限检查等,这种瞬时的高并发就容易成为性能瓶颈。

主从多线程模型(多Reactor多线程):

        Reactor主线程 MainReactor 对象通过select 监听连接事件, 收到事件后,通过Acceptor 处理连接事件 。

      当 Acceptor处理连接事件后,MainReactor 将连接(socketChannel)分配给SubReactor

      SubReactor将连接加入到连接队列进行监听,并创建handler进行各种事件处理。SubReactor有自己的Select,负责对应的读写事件等

      当有新事件发生时,SubReactor就会调用对应的handler处理

      handler通过read 读取数据,分发给后面的worker 线程处理

      worker线程池分配独立的worker 线程进行业务处理,并返回结果

      handler收到响应的结果后,再通过send 将结果返回给client

     Reactor主线程可以对应多个Reactor子线程, 即MainRecator 可以关联多个SubReactor。

        代码示例(实现了一个简单的主从多线程模型,一个MainReactor ,MainReactor 有一个主selector,专门维护accept事件,当接收到accept事件,交给SubReactor(也是一个),SubReactor有一个单独的从selector,从selector维护该连接的read和write事件):

        https://www.cnblogs.com/eason-ou/p/11912010.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值