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

2024-06-02 02:12

本文主要是介绍【图解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请求需要处理时,也不会影响到客户端建立连接的请求。

这篇关于【图解IO与Netty系列】Reactor模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1022749

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

DeepSeek模型本地部署的详细教程

《DeepSeek模型本地部署的详细教程》DeepSeek作为一款开源且性能强大的大语言模型,提供了灵活的本地部署方案,让用户能够在本地环境中高效运行模型,同时保护数据隐私,在本地成功部署DeepSe... 目录一、环境准备(一)硬件需求(二)软件依赖二、安装Ollama三、下载并部署DeepSeek模型选

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin