• Reactor和Proactor


    Reactor

    单 Reactor 单进程

    我们来看看「单 Reactor 单进程」的方案示意图:

    在这里插入图片描述

    可以看到进程里有 Reactor、Acceptor、Handler 这三个对象:

    1. Reactor 对象的作用是监听和分发事件;
    2. Acceptor 对象的作用是获取连接;
    3. Handler 对象的作用是处理业务;

    接下来,介绍下「单 Reactor 单进程」这个方案:

    1. Reactor 对象通过 select (IO 多路复用接口) 监听事件,收到事件后通过 dispatch 进行分发,具体分发给 Acceptor 对象还是 Handler 对象,还要看收到的事件类型;
    2. 如果是连接建立的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法 获取连接,并创建一个 Handler 对象来处理后续的响应事件;
    3. 如果不是连接建立事件, 则交由当前连接对应的 Handler 对象来进行响应;
    4. Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程。

    单 Reactor 单进程的方案因为全部工作都在同一个进程内完成,所以实现起来比较简单,不需要考虑进程间通信,也不用担心多进程竞争。

    但是,这种方案存在 2 个缺点:

    1. 因为只有一个进程,无法充分利用 多核 CPU 的性能;
    2. Handler 对象在业务处理时,整个进程是无法处理其他连接的事件的,如果业务处理耗时比较长,那么就造成响应的延迟;

    所以,单 Reactor 单进程的方案不适用计算机密集型的场景,只适用于业务处理非常快速的场景。

    单 Reactor 多线程

    先来看看「单 Reactor 多线程」方案的示意图如下:
    在这里插入图片描述

    详细说一下这个方案:

    1. Reactor 对象通过 select (IO 多路复用接口) 监听事件,收到事件后通过 dispatch 进行分发,具体分发给 Acceptor 对象还是 Handler 对象,还要看收到的事件类型;
    2. 如果是连接建立的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法 获取连接,并创建一个 Handler 对象来处理后续的响应事件;
    3. 如果不是连接建立事件, 则交由当前连接对应的 Handler 对象来进行响应;
    4. Handler 对象不再负责业务处理,只负责数据的接收和发送,Handler 对象通过 read 读取到数据后,会将数据发给子线程里的 Processor 对象进行业务处理;
    5. 子线程里的 Processor 对象就进行业务处理,处理完后,将结果发给主线程中的 Handler 对象,接着由 Handler 通过 send 方法将响应结果发送给 client;

    单 Reator 多线程的方案优势在于能够充分利用多核 CPU ,那既然引入多线程,那么自然就带来了多线程竞争资源的问题。要避免多线程由于竞争共享资源而导致数据错乱的问题,就需要在操作共享资源前加上互斥锁,以保证任意时间里只有一个线程在操作共享资源,待该线程操作完释放互斥锁后,其他线程才有机会操作共享数据。

    另外,「单 Reactor」的模式还有个问题,因为一个 Reactor 对象承担所有事件的监听和响应,而且只在主线程中运行,在面对瞬间高并发的场景时,容易成为性能的瓶颈的地方。

    多 Reactor 多线程

    要解决「单 Reactor」的问题,就是将「单 Reactor」实现成「多 Reactor」,多 Reactor 多线程方案的示意图如下:
    在这里插入图片描述

    方案详细说明如下:

    1. 主线程中的 MainReactor 对象通过 select 监控连接建立事件,收到事件后通过 Acceptor 对象中的 accept 获取连接,将新的连接分配给某个子线程;
    2. 子线程中的 SubReactor 对象将 MainReactor 对象分配的连接加入 select 继续进行监听,并创建一个 Handler 用于处理连接的响应事件。
    3. 如果有新的事件发生时,SubReactor 对象会调用当前连接对应的 Handler 对象来进行响应。
    4. Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程。

    Proactor

    前面提到的 Reactor 是非阻塞同步网络模式,而 Proactor 是异步网络模式。

    下图为 Proactor 模式的示意图:
    在这里插入图片描述

    Reactor和Proactor的区别

    • Reactor 是非阻塞同步网络模式,感知的是就绪可读写事件。在每次感知到有事件发生(比如可读就绪事件)后,就需要应用进程主动调用 read 方法来完成数据的读取,也就是要应用进程主动将 socket 接收缓存中的数据读到应用进程内存中,这个过程是同步的,读取完数据后应用进程才能处理数据。
    • Proactor 是异步网络模式, 感知的是已完成的读写事件。在发起异步读写请求时,需要传入数据缓冲区的地址(用来存放结果数据)等信息,这样系统内核才可以自动帮我们把数据的读写工作完成,这里的读写工作全程由操作系统来做,并不需要像 Reactor 那样还需要应用进程主动发起 read/write 来读写数据,操作系统完成读写工作后,就会通知应用进程直接处理数据。
  • 相关阅读:
    新零售数智化转型,需要怎样的数据底座?
    C++11标准模板(STL)- 算法(std::swap)
    【MySQL】慢SQL搜集工具、SQL脱敏聚合处理
    大数据业务场景
    如何读书
    STC单片机16——将输入信号2倍频
    如何使用baostock代码下载股票数据?
    输入一个url后,会发生什么事?
    剑指-019
    使用自定义注解实现Redis分布式锁
  • 原文地址:https://blog.csdn.net/TABE_/article/details/126361881