Reactor线程模型

线程模型

  • 一、背景
    • 1.socket网络通信
    • 2.IO模型与线程模型
    • 3.线程模型分类
      • 3.1 阻塞模型
      • 3.2 Reactor模型
      • 3.3 Proactor模式
  • 二、阻塞模型
    • 1.代码示例
  • 三、Reactor模型
    • 1.单Reactor单线程
      • 1.1 处理过程
      • 1.2 优缺点
      • 1.3 代码示例
    • 2.单Reactor多线程
      • 2.1 处理机制
      • 2.2 优缺点
    • 3.主从Reactor
      • 3.1 处理机制
      • 3.2 优缺点
  • 参考链接


一、背景

服务器需要等待客户端请求,在进行业务处理之后,将结果返回到客户端。其中服务器应用通过内核与网卡进行数据交互,具体原理和交互方式已在上一篇网络通信与IO多路复用中进行了详细介绍。

1.socket网络通信

客户端与服务器进行通信需要经过建立连接、请求、返回、关闭连接等步骤,而服务器需要监听客户端发起的创建连接、读取数据、业务处理、返回数据、关闭连接等步骤。
在这里插入图片描述

2.IO模型与线程模型

  • IO模型
    就是应用与内核读取socket数据的交互方式,已经在上一篇网络通信与IO多路复用中进行了详细介绍。
  • 线程模型
    服务器利用线程对从监听、创建连接、业务处理、关闭连接整个过程的处理方式。

3.线程模型分类

服务器处理一个网络请求需要经过以下步骤:

  • read:从socket读取数据
  • decode:解码,将网络上的流式byte转化成请求
  • compute:计算,主要是进行业务处理
  • encode:编码,将请求转化成流式byte数据

线程模型主要分为以下三类:

3.1 阻塞模型

服务端为每个客户端建立线程进行以上处理,一个线程为一个客户端服务。

3.2 Reactor模型

基于IO模型中的IO多路复用,服务端一个线程为多个客户端服务。

3.3 Proactor模式

基于IO模型中的异步IO,服务端一个线程为多个客户端服务。

二、阻塞模型

阻塞模型是针对每个客户端都会开启一个线程进行读事件处理以及业务处理。
在这里插入图片描述

1.代码示例

Reactor代码:

public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(9696);Socket socket = serverSocket.accept();new Thread(() -> {try {byte[] byteRead = new byte[1024];socket.getInputStream().read(byteRead);String req = new String(byteRead, StandardCharsets.UTF_8);//encode// do somethingbyte[] byteWrite = "Hello".getBytes(StandardCharsets.UTF_8);//decodesocket.getOutputStream().write(byteWrite);} catch (IOException e) {e.printStackTrace();}}).start();} catch (IOException e) {e.printStackTrace();}}

三、Reactor模型

Reactor模型主要是利用IO多路复用,利用少量线程为处理所有客户端的连接请求和读写请求。主要包含一下几部份:

  • Reactor:利用IO多路复用,监控连接请求就绪和读写请求就绪
  • Acceptor:接受客户端连接请求并创建连接,然后注册到Reactor的多路复用Selector中
  • Handle:对客户端的写请求进行读写编码和业务处理

1.单Reactor单线程

在这里插入图片描述

1.1 处理过程

  • Reactor构建Selector,监控port的连接事件并注册到Selector,并添加连接事件处理方法Acceptor
  • 有连接请求后,会触发Acceptor逻辑,会创建socketChannel并将此socketChannel的读事件注册到Reactor的Selector,并添加读事件处理方法Handle
  • 如果有读请求,会触发Handle事件,进行业务处理

1.2 优缺点

一个线程需要处理连接请求、读写请求、业务处理,处理业务请求会想对较慢。需要等待业务处理完成,才能对其他请求进行处理。
单线程Reactor模型编程比较简单,比较适合业务处理可以快速完成的场景,比如Redis。

1.3 代码示例

Reactor代码:

static class Reactor implements Runnable {ServerSocketChannel serverSocketChannel;Selector selector;public Reactor(int port) {try {serverSocketChannel = ServerSocketChannel.open();selector = Selector.open();// 监听port端口serverSocketChannel.socket().bind(new InetSocketAddress(port));serverSocketChannel.configureBlocking(false);// 注册连接事件SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_CONNECT);// 在连接事件上附加一个处理类selectionKey.attach(new Acceptor(selector, serverSocketChannel));} catch (IOException e) {System.out.println(e);}}@Overridepublic void run() {while (true) {try {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();dispatcher(selectionKey);iterator.remove();}} catch (Exception e) {}}}private void dispatcher(SelectionKey selectionKey) {Runnable runnable = (Runnable) selectionKey.attachment();runnable.run();}}

Acceptor与WorkHandle代码:

static class Acceptor implements Runnable {Selector selector;ServerSocketChannel serverSocketChannel;public Acceptor(Selector selector, ServerSocketChannel serverSocketChannel) {this.selector = selector;this.serverSocketChannel = serverSocketChannel;}@Overridepublic void run() {try {SocketChannel socketChannel = serverSocketChannel.accept();SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);selectionKey.attach(new WorkHandle(socketChannel));} catch (Exception e) {}}}static class WorkHandle implements Runnable {SocketChannel socketChannel;public WorkHandle(SocketChannel socketChannel) {this.socketChannel = socketChannel;}@Overridepublic void run() {try {ByteBuffer byteBuffer = ByteBuffer.allocate(1024);socketChannel.read(byteBuffer);socketChannel.write(ByteBuffer.wrap("message received".getBytes(StandardCharsets.UTF_8)));} catch (Exception e) {}}}

2.单Reactor多线程

单Reactor多线程主要是将业务处理进行多线程处理,其他操作还是由单线程处理。
在这里插入图片描述

2.1 处理机制

从整体架构图可知,整个处理机制与Reactor单线程模式基本一致。单个线程还是需要负责处理连接和读写请求,但是业务处理会提交到线程池进行处理。

2.2 优缺点

此模型不会因为业务处理相对较慢,而导致IO请求出现等待的情况。但是由于Reactor既要负责连接请求还需要负责读写请求。一个客户端一般只有一次连接请求,但是会有多次读写请求。如果有频繁的读请求,单个线程处理可能会导致无法及时处理其他读请求。

3.主从Reactor

主从Reactor模型主要是利用一个主Reactor监控连接请求就绪、一个或者多个子Reactor监控读请求就绪,业务请求还是通过线程池处理。
在这里插入图片描述

3.1 处理机制

从整体架构图可知,整个处理机制与Reactor多线程模式基本一致。单个线程负责处理连接请求,一个或者多个线程负责处理读写请求,业务处理会提交到线程池进行处理。

3.2 优缺点

此模型逻辑处理相对比较复杂。但是由于将连接请求还需要读写请求进行了拆分处理,可以很好的支持频繁的读写请求场景。


参考链接

1.Reactor模型

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

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

相关文章

Ubuntu Desktop 设置 gedit

Ubuntu Desktop 设置 gedit 1. View2. Editor3. Font & Colors4. keyboard shortcut5. Find and ReplaceReferences gedit (/ˈdʒɛdɪt/ or /ˈɡɛdɪt/) is the default text editor of the GNOME desktop environment and part of the GNOME Core Applications. Desig…

[蓝桥杯 2015 省 B] 生命之树

水一水的入门树形DP #include<iostream> #include<algorithm> #include<vector> using namespace std; using ll long long; #define int long long const int N 2e610; const int inf 0x3f3f3f3f; const int mod 1e97;int n; int w[N]; vector<vecto…

Unity双击全屏UI按钮、长按UI按钮

1.长按按钮 将下面的代码挂载到按钮上&#xff0c;去掉按钮本射的Button组件 using System.Collections; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems;public class LongPressButton : MonoBehaviour, IPointerDownHandler, IPointerUpHand…

递推与递归

92. 递归实现指数型枚举 - AcWing题库 #include <bits/stdc.h> using namespace std; const int N17; int n; bool vis[N];//记录某一个数是否出现过 void dfs(int dep){// if(vis[dep])continue;//没有这一句 因为一定不会有已经选过的数if(depn1){//对于每个数都做完了…

NCP1031DR2G集成DC-DC转换器 为以太网供电设备提供低成本、高可靠性解决方案

NCP1031DR2G是微型高电压单片 DC-DC 转换器&#xff0c;带有片上电源开关和启动电路。使用极少的外部部件&#xff0c;将实施若干开关稳压器应用所需的所有有源电源、控制逻辑和保护电路相结合&#xff0c;这些应用有辅助侧偏置电源和低功率 DC-DC 转换器。此控制器系列适用于 …

Learn OpenGL 17 立方体贴图

立方体贴图 我们已经使用2D纹理很长时间了&#xff0c;但除此之外仍有更多的纹理类型等着我们探索。在本节中&#xff0c;我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型&#xff1a;立方体贴图(Cube Map)。 简单来说&#xff0c;立方体贴图就是一个包含了…

OpenCV Steger算法提取条纹中心线

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 Steger 算法是一种常用的图像边缘检测算法,可以用于提取图像中的中心线或边缘信息。它的理论假设是:条纹的亮度是按照高斯分布呈现的,即中心亮两侧渐暗。 其计算过程如下所述: 1、首先,我们需要计算每个点Hess…

Kali Linux结合cpolar内网穿透实现公网环境SSH远程访问

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过[cpolar 内网穿透](cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站)软件实现ssh 远程连接kali! …

鸿蒙开发实战案例—QQ联系人开发教程

本次案例挑选了QQ4个tab中相对较难的一个页面进行开发 先看一下本次案例的最终效果图&#xff1a; 这个页面的难点在于在List组件又嵌套了一个可以左右滑动的联系人分类&#xff0c;以及好友分组的展开和收起。 现在我们从上到下来开发这个界面&#xff0c;首先是导航栏&…

适合一个人开的实体店:轻松创业,快速盈利的秘诀

在当今的创业潮流中&#xff0c;很多人都渴望拥有一份属于自己的事业。如果你也想独自创业&#xff0c;开一家实体店&#xff0c;那么这篇文章将为你提供一些有价值的干货信息。作为一名经营5年酸奶吧的创业者&#xff0c;我将分享一些经验和见解&#xff0c;帮助你轻松创业并实…

【MD】金属-半导体界面超快辐射诱导熔化的分子动力学模拟

这篇文章是一篇发表在《Journal of Applied Physics》上的论文&#xff0c;标题为“Molecular dynamics simulations of ultrafast radiation induced melting at metal–semiconductor interfaces”&#xff0c;作者为Ashwin Ravichandran, Mohit Mehta, Andrew A. Woodworth,…

Python爬虫案例-爬取主题图片(可以选择自己喜欢的主题)

2024年了&#xff0c;你需要网络资源不能还自己再慢慢找吧&#xff1f; 跟着博主一块学习如何利用爬虫获取资源&#xff0c;从茫茫大海中寻找那个她到再妹子群中找妹子&#xff0c;闭着眼睛都可以找到合适的那种。文章有完整示例代码&#xff0c;拿过来就可以用&#xff0c;欢迎…

洛谷 [传智杯 #5 初赛] B-莲子的机械动力学

题目链接&#xff1a;[传智杯 #5 初赛] B-莲子的机械动力学 题目背景 【题目背景和题目描述的两个题面是完全等价的&#xff0c;您可以选择阅读其中一部分。】 专攻超统一物理学的莲子&#xff0c;对机械结构的运动颇有了解。如下图所示&#xff0c;是一个三进制加法计算器的…

Django 反向解析路由

app2.urls.py from django.urls import path, re_path from . import viewsurlpatterns [path(index, views.index, nameindex),path(url_reverse, views.url_reverse, nameapp2_url_reverse), # 使用reverse()方法反向解析 ,name对于视图的reverse("app2_url_reverse&…

面临挑战:共享WiFi贴项目能否长久存在?

共享WiFi贴项目会长久吗&#xff1f;这个问题是很多创业者想要了解的事情&#xff0c;随着5G网络和共享经济的兴起&#xff0c;共享WiFi贴项目应运而生。在这个信息时代&#xff0c;网络已成为人们日常生活中不可或缺的一部分&#xff0c;而WiFi作为网络的一种接入方式&#xf…

什么是大型语言模型(LLM)?

大型语言模型 (LLM) 是一种能够理解和生成人类语言文本的机器学习模型。它们通过分析大量语言数据集来工作。 一、什么是大型语言模型 (LLM)&#xff1f; 大型语言模型 (LLM) 是一种人工智能 (AI) 程序&#xff0c;它可以识别和生成文本以及完成其他任务。LLM 经过了庞大的数据…

(vue)Module Error (from ./node_modules/eslint-loader/index.js)

(vue)Module Error (from ./node_modules/eslint-loader/index.js) 方法1&#xff1a;直接关闭eslint // vue.config.js module.exports {lintOnSave: false, //关闭eslint语法检查...... }方法2&#xff1a; 参考&#xff1a;解决参考 解决参考&#xff1a;如何修复vue-cli…

Ollama 运行 Cohere 的 command-r 模型

Ollama 运行 Cohere 的 command-r 模型 0. 引言1. 安装 MSYS22. 安装 Golang3. Build Ollama4. 运行 command-r 0. 引言 Command-R Command-R 是一种大型语言模型&#xff0c;针对对话交互和长上下文任务进行了优化。它针对的是“可扩展”类别的模型&#xff0c;这些模型在高…

uniapp+uview 学习笔记(二)—— H5开发

文章目录 前言一、开发步骤1.创建项目2.安装组件库并导入使用3.封装请求4.国际化5.打包 总结 前言 本文主要介绍使用uniapp框架和uview组件库进行H5开发&#xff0c;需要用到的开发工具为HBuilder X。 一、开发步骤 1.创建项目 打开HBuilder X&#xff0c;在顶部栏目选择 新…

网络安全框架和云安全参考架构介绍

目录 一、网络安全框架 1.1 概述 1.2 IATF框架 1.2.1 框架来源 1.2.2 框架结构图 1.2.3 框架内容 1.2.3.1 人&#xff08;People&#xff09; 1.2.3.2 技术&#xff08;Technology&#xff09; 1.2.3.3 操作&#xff08;Operation&#xff09; 1.3 NIST网络安全框架 …