【图解IO与Netty系列】Reactor模型

Reactor模型

  • Reactor模型简介
    • 三类事件与三类角色
    • Reactor模型整体流程
  • 各种Reactor模型
    • 单Reactor单线程模型
    • 单Reactor多线程模型
    • 主从Reactor模型

Reactor模型简介

Reactor模型是服务器端用于处理高并发网络IO请求的编程模型,与传统的一请求一线程的同步式编程模型不同的是,Reactor模型是基于事件驱动的响应式编程模型,可以一个线程处理多个请求,并且是异步处理,在高并发场景下,性能大大的提升。

传统的同步式编程模型如下:

在这里插入图片描述

服务端接收到请求后,从线程池中拿出一个线程(比如Tomcat里的线程池),经过Controller、Service、Dao的一顿处理,最后返回响应结果给客户端。这种同步处理请求的方式效率并不高,可以应对一些并发量不高的场景。

基于事件驱动的响应式编程模型如下:
在这里插入图片描述

  1. 服务端启动时,会创建Reactor反应器,然后会向Reactor注册基本的事件类型与对应的Handler(比如网络编程时的连接就绪事件与Acceptor)
  2. 当服务端接收到客户端的请求时,服务端的Reactor就有事件就绪,Reactor会获取到就绪的事件,在高并发场景下,Reactor有可能获取到一批就绪的事件
  3. Reactor进事件分发,把事件分派给与之绑定的Handler中,Handler对事件的处理可以在当前线程中也可以在线程池中,当然在线程池中处理性能会更高
  4. Handler处理完毕后,如果后续还有其他处理步骤,则可以继续注册新的事件与对应的Handler到Reactor中;如果没有后续,则可以返回响应结果给客户端,返回响应结果这个动作可作为单独的一个事件,由对应的Handler进行处理,那么也可以继续注册到Reactor中。

Reactor其实就是一个线程,可以看到它就在一个死循环中进行事件监听以及事件分派,这就是事件循环。

Reactor模型底层使用了IO多路复用,通过对IO多路复用机制的合理利用,使得服务器端达到高效的处理网络IO请求的目的。我们可以使用Java提供的NIO来实现Java版本的Reactor模型。
在这里插入图片描述

三类事件与三类角色

Reactor模型抽象了三类事件和三类角色,它们是Reactor模型的核心组成部分。三类事件是:连接就绪事件,读就绪事件、写就绪事件。三类角色是:Reactor、Acceptor、Handler。

首先我们来了解一下三类事件。

在这里插入图片描述

  • 连接就绪事件:客户端向服务端发起连接的时候,对应的Channel就有连接就绪事件发生。
  • 读就绪事件:当客户端向服务器端发送数据时,对应的Channel就有读就绪事件发生。
  • 写就绪事件:当服务器处理完客户端发送的数据,需要返回结果时,可以向Selector注册一个写就绪事件并与对应的Channel关联,那么对应Channel就有写就绪事件发生。

我们再来了解一下三类角色。
在这里插入图片描述

Reactor是相当于是一个事件分派器,Reactor专门负责监听事件的发生,并把发生的事件交给对应的处理器处理,这里的处理器指的就是Acceptor或Handler。Reactor是一个线程,它通过Selector注册并监听多个Channel,如果监听到有事件发生,判断是连接就绪事件,会交给Acceptor处理,如果发生的事件是读就绪事件或写就绪事件,会交给Handler处理。

在这里插入图片描述

如果是连接就绪事件,Reactor会将其分派给Acceptor处理,Acceptor会调用accept()方法获取到连接对应的SocketChannel,然后会将其设置为非阻塞,注册到Reactor的Selector中,设置关注的事件为读就绪事件。

在这里插入图片描述

如果是读就绪事件,那么Reactor会将其分派给与其绑定的Handler处理,该Handler会经过read、decode、compute、encode、send五个步骤的处理。

  1. read:读取Channel中的数据
  2. decode:对读到的数据进行解码
  3. compute:解码后的数据进行相应处理
  4. encode:对处理后的结果进行编码
  5. send:编码后的数据发送给客户端。

之所以要进行decode和encode,是因为数据在网络上是以二进制的形式传输的,因此服务端接收到后要对二进制字节码进行解码操作,然后才能对解码后的数据进行处理,处理完的数据要发送到网络,也要编码成二进制的格式。

在这里插入图片描述

其中,send操作可以立刻发送数据写出到Channel,也可以注册一个写就绪事件到Selector,这就相当于进行异步发送。

在这里插入图片描述

Reactor模型整体流程

在这里插入图片描述

  1. 首先,一开始我们只把ServerSocketChannel以及连接事件处理器Acceptor注册到Reactor中,Reactor会把ServerSocketChannel注册到Selector中,并设置关注连接就绪事件
  2. 一旦客户端发起连接,ServerSocketChannel的连接就绪事件就绪,Reactor会将其分派给Acceptor处理,Acceptor会获取到连接对应的SocketChannel,并将其与对应的处理器Handler注册到Reactor,Reactor会将其注册到Selector中。
  3. 随后客户端向服务端发送数据,Reactor监听到对应的SocketChannel有读就绪事件发生,会将其分派给与其绑定的Handler进行处理。
  4. Handler被分派到读就绪事件时,会经过read、decode、compute、encode、send五个步骤的处理。
  5. 服务端要把处理结果返回给客户端,会向Reactor注册一个对应Channel的写就绪事件,Reactor监听到写就绪事件,会分派给与该Channel绑定的Handler处理,Handler把返回结果发送出去。

各种Reactor模型

Reactor编程模型不是只有单一的一种编程模型,它有单Reactor单线程模型、单Reactor多线程模型、主从Reactor模型等多种模型。

单Reactor单线程模型

单Reactor单线程模型是最简单的模型,当然性能也是最低的。单Reactor模型只有一个Reactor,这个Reactor即负责处理连接建立,也负责数据读写和计算等处理。并且由于是单线程模型,所以数据读取后的计算处理,也是在当前线程中完成。

在这里插入图片描述

这种单Reactor单线程模型虽然性能比其他的Reactor模型低,但是优点是比较的简单,没有了多线程就意味着没有了“多线程翻车”的一些情况出现。值得一提的是,Redis的事件驱动框架就是单Reactor单线程模型

但是由于连接建立与IO处理都在一个Reactor线程中进行,因此在高并发场景下,该Reactor线程的压力会非常大,特别是在数据计算还比较复杂的场景,单线程的Reactor模型有可能支撑不住。之所以Redis使用单Reactor单线程模型还能支撑高并发读写的场景,其中一个原因是因为Redis内部不涉及太复杂的数据计算。

单Reactor多线程模型

单Reactor多线程模型是在单Reactor模型的基础上增加了线程池,可以把decode、compute、encode等需要计算的操作提交到线程池执行,而Reactor线程则专注于连接建立与IO的处理(也就是read和send)。

在这里插入图片描述

把涉及到计算的处理抽到了线程池中处理,可以在一定程度上缓解Reactor线程的压力。但是由于还是单Reactor模型,IO处理依然在该Reactor线程中进行,高并发场景下,可能会由于大量的IO请求需要处理而导致连接建立的处理受到影响,该Reactor线程可能无法及时响应客户端连接建立的请求。

主从Reactor模型

主从Reactor模型在单Reactor多线程模型基础上做了改进,把IO处理分离到了子Reactor中,主Reactor只专注于连接请求的处理,主Reactor一般只有一个(也可有多个),而子Reactor一般有多个。当主Reactor上有连接就绪事件发生时,通过Acceptor获取到连接对应的SocketChannel,然后把该SocketChannel注册到子Reactor中,由子Reactor监听该Channel的读就绪事件并处理。

在这里插入图片描述

由于连接建立与IO处理分离到了不同的Reactor,当有大量并发的IO请求需要处理时,也不会影响到客户端建立连接的请求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/20555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

翼龙面板是什么,如何进行搭建

翼龙面板是一个开源的,用于游戏服务器管理的程序,可以方便地在网页界面中创建Minecraft,起源引擎游戏和Teamspeak3 服务器。 它使用前后端程序,因此可以创建多后端节点,对游戏服务器和服务器节点进行统一管理。 对游戏…

Vue进阶之Vue无代码可视化项目(二)

Vue无代码可视化项目 项目初始化路由子路由错误示范正确示范App.vuerouter/index.tsAboutView.vueAboutAboutview.vuerouter/index.ts项目路由router/index.tsApp.vueActionsView.vueDataSourceView.vueLayoutView.vue路由样式App.vue进一步的App.vue项目初始化 路由 router i…

synchronized 锁的到底是什么?

通过8种情况演示锁运行案例,看看我们到底锁的是什么 1锁相关的8种案例演示code package com.bilibili.juc.lock;import java.util.concurrent.TimeUnit;/*** 题目:谈谈你对多线程锁的理解,8锁案例说明* 口诀:线程 操作 资源类* 8…

修改hostname导致RabbitMQ数据丢失

背景介绍 公司的很多关键服务都使用了RabbitMQ来作为消息队列服务, 可以说是非常地关键的一个环节, 最近由于业务量的上升, 导致RabbitMQ的CPU持续走高, 所以抽空研究了一下RabbitMQ的扩容, 利用我们自己运维平台使用的一个单节点的RabbitMQ来作为测试吧.看到这个单节点的Rabbi…

第十七节 huggingface的trainner的断点续训的Demo(resume)

文章目录 前言一、参数决定权重保存1、model.safetensors保存2、scaler.pt保存3、optimizer.pt与scheduler.pt保存4、self.state状态保存(trainer_state.json)5、rng_state.pth保存6、权重相关保存位置(huggingface)二、Resume的Demo1、Demo构建2、实现Resume方法三、Resume训…

005 CentOS 7.9 RabbitMQ安装及配置

https://github.com/rabbitmq/rabbitmq-server/releases https://www.rabbitmq.com/docs/download https://packagecloud.io/rabbitmq/rabbitmq-server https://www.erlang-solutions.com/downloads/ https://www.erlang.org/ 文章目录 卸载erlerl版本安装与下载版本不匹配正…

AI技术的深度探索:重塑未来的智能引擎

随着科技的迅猛进步,人工智能(AI)技术已经逐渐渗透到我们生活的每一个角落,从简单的智能助手到复杂的决策支持系统,AI技术以其独特的方式和前所未有的速度改变着我们的世界。本文将对AI技术进行深入探讨,从…

开源贡献 | 基于长安链去中心化数字身份合约标准协议(CMDID-1)的DID

DID为每个实体(人、组织、物品等)提供了一个唯一的全球身份标识符,让用户可以控制和管理的自己的数字身份,并在使用时以最小化的方式出示,将数据所有权归还用户的同时以区块链技术保证了身份的不可篡改性,以…

LeetCode875爱吃香蕉的阿珂

题目描述 珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。每个小时,她将会选择一堆香蕉,从…

IntelliJ IDEA / Android Studio 方法显示Git提交人

显示方法: 设置 > 编辑器 > 嵌入提示 > Code Vision > 代码作者(勾选) IntelliJ IDEA Android Studio

springboot编写日志环境搭建过程

AOP记录日志 AOP记录日志的主要优点包括: 1、低侵入性:AOP记录日志不需要修改原有的业务逻辑代码,只需要新增一个切面即可。 2、统一管理:通过AOP记录日志可以将各个模块中需要记录日志的部分进行统一管理,降低了代…

神经网络的工程基础(二)——随机梯度下降法|文末送书

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型:从线性回归到通用人工智能》,欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下:regression2chatgpt/ch06_optimizer/stochastic_gradient_descent.ipynb 本文将讨论利用…

WinApp自动化测试之辅助工具介绍

前篇文章中,我们简单介绍了部分WinApp自动化测试脚本常规操作,今天我们来讲剩余的部分。 文件批量上传 文件批量上传和文件单个上传原理是相同的,单个上传直接传入文件路径即可,批量上传需要进入批量上传的文件所在目录&#xf…

Redis到底是AP还是CP?

这个问题差评,没问清楚。当然,网上一搜,各种各样的狗屁答案都有,有时候是AP的,有时候是CP的,薛定谔的Redis。 好的,那应该怎么问呢?Q1.Redis Cluster集群是AP还是CP? A…

uniapp创建支付密码实现(初始密码,第二次密码)

示例: 插件地址:自定义数字/身份证/密码输入框,键盘密码框可分离使 - DCloud 插件市场 1.下载插件并导入HBuilderX,找到文件夹,copy number-keyboard.vue一份为number-keyboard2.vue(number-keyboard.vue是…

C++ STL map容器erase操作避坑

map容器的erase方法有三种重载形式: //1.删除迭代器所指向的元素 //返回值是指向下一个节点的迭代器 iterator erase(iterator it); //2.区间删除 iterator erase(iterator first, iterator last); //3.根据键值删除 //返回值为删除的元素个数 size_type erase(con…

民国漫画杂志《时代漫画》第37期.PDF

时代漫画37.PDF: https://url03.ctfile.com/f/1779803-1248636302-c017ee?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

C++基础编程100题-002 OpenJudge-1.1-04 输出保留3位小数的浮点数

更多资源请关注纽扣编程微信公众号 002 OpenJudge-1.1-04 输出保留3位小数的浮点数 http://noi.openjudge.cn/ch0101/04/ 描述 读入一个单精度浮点数,保留3位小数输出这个浮点数。 输入 只有一行,一个单精度浮点数。 输出 也只有一行,…

块设备层保序操作分析

Q:块设备层保序功能的作用? A:通用块层可以提交一个带保序标签(BIO_RW_BARRIER)的BIO到IO请求队列,块设备层可以保证在保序BIO之前提交的BIO都先于BIO执行且抵达存储介质;保序BIO执行完毕后,它需要写入的数据必定已经抵达存储介质;在保序IO之后提交的BIO都晚于保序BIO执行,确保…

07.爬虫---使用session发送请求

07.使用session发送请求 1.目标网站2.代码实现 1.目标网站 我们以这个网站作为目标网站 http://www.360doc.com/ 注册用户 注册后从登录界面获取到这些信息 2.代码实现 import requestssession requests.Session() url http://www.360doc.com/ajax/login/login.ashx u…