Linux搭建Web服务器(三)——服务器编程基本框架以及事件处理模式

news2024/10/2 14:22:53

目录

0x01 服务器编程基本框架

0x02 两种高效的事件处理模式

Reactor 模式

Proactor 模式

模拟Proactor 模式


0x01 服务器编程基本框架

虽然服务器程序的种类繁多,但是其基本框架都是一样的,不同之处是在于处理逻辑。对于我们在这个服务器的搭建可以分为解析-读取-响应三个阶段。

 

  • I/O处理单元:处理客户连接,读写网络数据。它通常要完成以下工作:等待并接受新的客户连接,接收客户数据,将服务器响应数据返回给客户端。但是数据的收发不一定在 I/O 处理单元中执行,也可能在逻辑单元中执行,具体在何处执行取决于事件处理模式

  • 逻辑单元:业务进程或线程。通常是进程或线程。它分析并处理客户数据,然后将结果传递给 I/O 处理单元或者直 接发送给客户端(具体使用哪种方式取决于事件处理模式)。服务器通常拥有多个逻辑单元,以实现对多个客户任务的并发处理

  • 网络存储单元:可以是数据库、缓存和文件,但不是必须的。

  • 请求队列:是各单元之间的通信方式的抽象。I/O 处理单元接收到客户请求时,需要以某种方式通知一个 逻辑单元来处理该请求。同样,多个逻辑单元同时访问一个存储单元时,也需要采用某种机制来协调处理竞态条件。请求队列通常被实现为池的一部分。(进程池、线程池)

对于服务器模型,常见的有C/S模型,也就是常见的TCP服务器与客户端的工作流程,适合在资源相对集中的场合,服务器是通信中心,当访问量过大的适合,可能所有的客户都将面对很慢的响应。还有一种P2P模型,这种模型的每台机器既是主机也是服务器,当用户之间传输请求过多时,网络的负载将加重。

对于两种高效的并发模式:并发模式是指I/O处理单元和多个逻辑单元之间协调完成任务的方法。两种并发编程模式:半同步/半异步模式、领跑者/追随者模式。

半同步/半异步模式

  • 同步:程序完全按照代码序列的顺序执行——同步线程

  • 异步:程序的执行需要有系统事件来驱动,如中断、信号等——异步线程

在半同步/半异步模式中,同步线程用于处理客户逻辑,异步线程用于处理I/O事件。异步线程监听到客户请求后,将其封装成请求对象并插入请求队列中。请求队列将通知某个工作在同步模式的工作线程来读取并处理请求对象。

如果结合考虑两种事件处理模式和几种I/O模型,半同步/半异步模式就存在多种变体:

  • 半同步/半反应堆模式:异步线程只有主线程,同步线程为多个工作线程

  • 高效的半同步/半异步模式:主线程只负责监听socket,连接socket由工作线程来管理

领跑者/追随者模式

  • 领导者/追随者模式是多个工作线程轮流获得事件源集合,轮流监听、分发并处理事件。

  • 在任意的时间点,程序都仅有一个领导者进程,它负责监听I/O事件;其他线程则都是追随者,它们休眠在线程池中等待成为新的领导者。

  • 当前的领导者如果检测到I/O事件,首先要从线程池中推选出新的领导者线程,然后处理I/O事件。此时,新的领导者等待新的I/O事件而原来的领导者则处理I/O事件,二者实现了并发。

需要的组件有如下:

  • 句柄集(HandleSet):句柄I/O资源,通常为一个文件描述符;句柄集使用wait_for_event监听I/O事件等

  • 线程集(ThreadSet):所有工作进程的管理者,负责各线程之间的同步,以及新领导者的推选;三种状态:Leader,Processing 和Follower

  • 事件处理器(EventHander)和 (ConcreteEventHandler):包含一个或多个回调函数handle_event

缺点:领导者/追随者模式仅支持一个事件源集合,无法让每个工作线程独立的管理多个客户连接

0x02 两种高效的事件处理模式

服务器程序通常需要处理三类事件:I/O 事件、信号及定时事件。有两种高效的事件处理模式:Reactor 和 Proactor:

  • 同步 I/O 模型通常用于实现 Reactor 模式

  • 异步 I/O 模型通常用于实现 Proactor 模式

其中异步IO的模式可以使用同步IO来进行模拟得出。

Reactor 模式

在这里只考虑线程,在这里要使用多线程进行并发处理,在这里有主线程以及子线程,要求主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元),将 socket 可读可写事件放入请求队列,交给工作线程处理(子线程)。除此之外,主线程不做任何其他实质性的工作。读写数据,接受新的连接,以及处理客户请求均在工作线程中完成。(只负责监听)

主要的工作流程如下:

使用同步 I/O(以 epoll_wait 为例)实现的 Reactor 模式的工作流程是:

  1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。

  2. 主线程调用 epoll_wait 等待 socket 上有数据可读。

  3. 当 socket 上有数据可读时, epoll_wait 通知主线程。主线程则将 socket 可读事件放入请求队列

  1. 睡眠在请求队列上的某个工作线程被唤醒,它从 socket 读取数据,并处理客户请求,然后往 epoll内核事件表中注册该 socket 上的写就绪事件。

  2. 主线程调用 epoll_wait 等待 socket 可写。

  3. 当 socket 可写时,epoll_wait 通知主线程。主线程将 socket 可写事件放入请求队列

  4. 睡眠在请求队列上的某个工作线程被唤醒,它往 socket 上写入服务器处理客户请求的结果。

在这里,主进程只负责监听以及工作交互,子线程负责对事件进行读写。

Proactor 模式

Proactor 模式将所有 I/O 操作都交给主线程和内核来处理(进行读、写),工作线程仅仅负责业务逻辑。使用异步 I/O 模型(以 aio_read 和 aio_write 为例)实现的 Proactor 模式的工作流程是:

 

 

区别在于数据是否在主线程中进行处理,也就是同步与异步的区别,直接得到了数据的读写结果。

  1. 主线程调用 aio_read 函数向内核注册 socket 上的读完成事件,并告诉内核用户读缓冲区的位置,以及读操作完成时如何通知应用程序(这里以信号为例)。

  2. 主线程继续处理其他逻辑。

  3. 当 socket 上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据已经可用

  4. 应用程序预先定义好的信号处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求后,调用 aio_write 函数向内核注册 socket 上的写完成事件,并告诉内核用户写缓冲区的位置,以及写操作完成时如何通知应用程序。

  5. 主线程继续处理其他逻辑。

  6. 当用户缓冲区的数据被写入 socket 之后,内核将向应用程序发送一个信号,以通知应用程序数据已经发送完毕。

  7. 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭 socket。

模拟Proactor 模式

使用同步 I/O 方式模拟出 Proactor 模式。原理是:主线程执行数据读写操作,读写完成之后,主线程向工作线程通知这一”完成事件“。那么从工作线程的角度来看,它们就直接获得了数据读写的结果,接下来要做的只是对读写的结果进行逻辑处理。

使用同步 I/O 模型(以 epoll_wait为例)模拟出的 Proactor 模式的工作流程如下:

  1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。

  2. 主线程调用 epoll_wait 等待 socket 上有数据可读。

  3. 当 socket 上有数据可读时,epoll_wait 通知主线程。主线程从 socket 循环读取数据,直到没有更多数据可读,然后将读取到的数据封装成一个请求对象并插入请求队列

  4. 睡眠在请求队列上的某个工作线程被唤醒,它获得请求对象并处理客户请求,然后往 epoll 内核事件表中注册 socket 上的写就绪事件。

  5. 主线程调用 epoll_wait 等待 socket 可写。

  6. 当 socket 可写时,epoll_wait 通知主线程。主线程往 socket 上写入服务器处理客户请求的结果。

其Reactor模式与Proactor模式做个简单的区分主要在于如下:

Reactor模式——当事件就绪,通知工作线程。

Proactor模式——当事件就绪,内核完成读写后,通知工作线程。

 

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

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

相关文章

基于Jenkins实现Docker应用的持续集成与部署

先决条件 1. 服务器部署安装有docker 在docker应用开发中最常见的就是开发Dockerfile文件,可以使用代码仓库来管理它。 而在企业私有开发环境中是无法访问公有代码仓库(如Github)的。这时可以搭建私有代码仓库。 部署安装svn私有仓库 安…

GPT-4 验明真身的三个经典问题:快速区分 GPT-3.5 与 GPT-4

现在已经有很多 ChatGPT 的套壳网站,以下分享验明 GPT-4 真身的三个经典问题,帮助你快速区分套壳网站背后到底用的是 GPT-3.5 还是 GPT-4。 测试问题 1:What is tomorrow in relation to yesterday’s today?(昨天的当…

《Shunted Transformer: Shunted Self-Attention》CVPR 2022 oral

论文链接:https://openaccess.thecvf.com/content/CVPR2022/papers/Ren_Shunted_Self-Attention_via_Multi-Scale_Token_Aggregation_CVPR_2022_paper.pdf 代码链接:https://github.com/OliverRensu/Shunted-Transformer​ 1. 动机 视觉转换器(ViT)模型…

vscode怎么对选定的代码格式化?ctrl+k,ctrl+f(格式化代码)

先选中代码: 然后按CTRL K 再按CTRLF 也可以先选择要格式化的代码块,ctrlshiftp,搜索format,然后第二个就是:

助你掌握搜索神器,10个实用的Elasticsearch查询技巧

前言 Elasticsearch是一个非常流行的搜索引擎,已经成为了许多企业的首选解决方案。然而,我们要想成为一个优秀的程序员,就必须掌握各种查询技巧。本文将向大家介绍10个实用的Elasticsearch查询技巧,并配上详细的代码示例&#xff…

Python基础实战1-简单介绍python

1 Python介绍 Python是一门优雅而健壮的编程语言,它继承了传统编程语言的强大性和通用性,同时也借鉴了脚本语言和解释语言的易用性。 1.1 Python的历史 Python是由创始人贵铎范罗萨姆(Guido van Rossum)在阿姆斯特丹于1989年圣…

在数字化质变“奇点”时刻,看数字生产力跃升的华为观

(华为轮值董事长孟晚舟) 进入2023年,以大语言模型为代表的新AI,打开了全球对于数字生产力的全新认知:高盛集团经济学家认为,ChatGPT等生成式AI最终可能在10年的时间里使得全球年GDP增长7%(近7万…

pinia持久化存储方案——pinia-storage(自己写的,持续更新)

pinia持久化存储方案——pinia-storage pinia-storagepinia-storage Introduction版本更新说明(update introduction)安装(install)npm 安装(npm install) QuickStartcreate piniastore/indexstore/indexPinia.tsstore/indexPinia.js main.ts | main.jsA…

Direct3D 12——几何着色器——几何着色器概念

几何着色器 几何着色器这个可选阶段便位于顶点着色器与像素着色器之间。几何着色器所输出的图元由顶点列表定义而成。在退岀几何着色器时,必将顶点的位置变换到齐次 裁剪空间。换言之,经过几何着色器阶段的处理后,我们就得到了位于齐次裁剪空…

MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点3:EXPLAIN ANALYZE

文章目录 MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点3:EXPLAIN ANALYZEEXPLAIN ANALYZE介绍EXPLAIN ANALYZE的特性EXPLAIN 和EXPLAIN ANALYZE的结果对比例题例题解析参考 MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点3:EXPLAIN ANALYZE EXPLAIN…

部门来了个测试人,听说是00后,上来一顿操作给我看呆了...

今天上班开早会就是新人见面仪式,听说来了个很厉害的大佬,年纪还不大,是上家公司离职过来的,薪资已经达到中高等水平,很多人都好奇不已,能拿到这个薪资应该人不简单,果然,自我介绍的…

网络原理(TCP/UDP)

目录 一. 网络基础 1. IP地址 2. 端口号 3. 协议 4. OSI七层模型 二. UDP协议 2.1 UDP的协议端格式: 2.2 UDP的特点 三. TCP协议 3.1 TCP协议段格式 3.2 TCP原理 (1)确认应答机制 (2)超时重传机制 &#xff…

CmBacktrace库在工程中的添加和应用

CmBacktrace 介绍在工程中添加CmBacktrace断言打印全局变量的值循环输出错误信息串口处理看门狗处理 介绍 CmBacktrace下载 CmBacktrace (Cortex Microcontroller Backtrace)是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错…

Javaee Spring template实现查询数据库表内容 基于半xml半注解

昨天用基于xml配置实现template查询数据库,今天基于半xml半注解方式实现,使用注解需要导入spring-aop-5.3.8.jar 导入jar包 项目结构: 其他代码在,先前上一篇文章已经给出 AccountServiceImpl package wwx.dao;import org.springframework…

定时器中断实验

实现内容 利用TIM3的定时器中断来控制DS1的翻转,在主函数用DS0 的翻转来提示程序正在运行。 定时器介绍 定时器可以认为是一个计数器;给定计数器一个初值,每当计数一次,就会走过一个固定的时间,当达到我们给定的初值…

强大的图像处理:ImageKit10.E ActiveX Crack

强大的图像处理! ImageKit10 ActiveX 是一个组件,允许您快速轻松地向应用程序添加图像处理功能。使用 ImageKit10 ActiveX,您可以编写从 TWAIN 扫描仪和数码相机检索图像的应用程序;加载和保存图像文件并将图像从一种格式转换为另一种格式;编…

数字电路和模拟电路-半导体三极管

目录 1 什么是三极管? 1.1 放大状态时的偏执条件 1.1.1发射结加正向电压,扩散运动形成发射极电流IE 1.1.2扩散到基区的自由电子与空穴的复合运动形成基极电流IB 1.1.3集电结加反向电压,漂移运动形成集电极电流Ⅰc 2 三极管工作原理 2.…

5.图论(0x3f:从周赛中学算法 2022下)

来自0x3f【从周赛中学算法 - 2022 年周赛题目总结(下篇)】:https://leetcode.cn/circle/discuss/WR1MJP/ 周赛中的图论题目比较少,除了下面选的 DFS、BFS、拓扑排序、基环树、二分图判定等,还有最短路、DFS 时间戳等&a…

CloudCompare二次开发之如何设计界面ui与功能实现?

文章目录 0.引言1.创建界面ui相关文件2.添加界面ui相关文件到CloudCompare工程3.修改工程相关文件4.结果展示 0.引言 CloudCompare源代码编译成功后,即可进行二次开发,可以通过修改源码实现二次开发,二次开发基础功能见(CloudComp…

什么是文件共享软件?文件传输软件如何共享?

它是一个文件共享软件应用程序,可让强大的数据保护层下将任何大小的文件发送到世界上的任何地方。以光速发送和共享无限数量的文件。可以提交门户并使用语言,品牌,存储等自定义门户。可以选择一个存储点,例如文件传输软件&#xf…