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

目录

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模式——当事件就绪,内核完成读写后,通知工作线程。

 

Webadmin!是一个免费的开源框架,用于为Linux系统的快速搭建统一、稳定、易用的Web管理系统。 WebAdmin系统由部分组成:WEB图形用户接口、WebAdmin守护进程和进程监视程序。Web图形用户接口(WebGUI)是WebAdmin系统的前端部分,为用户提供一个统一、易操作的图形界面。WebAdmin守护进程 (WebAdmind)是WebAdmin系统的后台部分,实时监视WebGUI生成的配置文件,并根据配置文件的变化情况,启动或停止相应的服务进程,WebAdmin进程监视程序(DaemonWatcher)用于实时监视WebAdmind启动的服务进程的运行状况,一旦发现启动的服务进程异常中止,立即重启中止的服务进程,从而确保系统可靠稳定运行。 WebAdmin!提供了一个结构化的WebAdmin开发框架,它的前后台部分均采用插件式的程序开发方法,借助提供的插件开发模板,WebAdmin系统开发者不必关WebAdmin开发框架的具体实现,就可设计出界面统一、操作简单、安全稳定的WebGUI界面。与WebGUI相对应,Webadmind也是采用插件式的程序开发方法。WebAdmind插件与WebGUI插件一一对应完成对界面操作的响应。DaemonWatcher是一个独立的进程监视程序,是为确保WebAdmind启动的进程能够不可间断地提供服务,一旦发现被监视程序发生异常中止,DaemonWatcher将根据进程的启动脚本立即启动被中止进程。 WebAdmin是一个用C语言设计的易用的图形用户接口开发框架,C语言的高可移植性使得WebAdmin可以广泛应用于包括Linux、Unix、Windows及各种嵌入式操作系统中,编译WebAdmin系统除Libxml2库处不需要额外的C函数库支持。WebAdmin提供了丰富的API函数,开发者可以根据自己的需要定制个性化的WebAdmin系统。 WebAdmin系统的界面风格也可以自己定制,对于OEM厂商可以根据需要修改界面风格,满足定制要求。 WebAdmin的开放设计思想,为WebAdmin系统的不断发展普奠定了基础,无数开发者提供了开源插件模块,用户甚至不用写一行代码就可根据自己的需要设计WebAdmin系统。 【简单使用方法】:下载后将压缩文件上传到Linux系统中,用tar xvfz webadmin-devel-1.3.tar.gz解压,解压后进入webadmin-devel目录,执行./configure,make命令后将会在test/webui目录下生成一个webadmin.cgi文件,将此文件拷贝到apache下的WEB根目录下cgi-bin目录下即可,为测试webadmin.cgi,还需将htdocs目录下的文件拷贝到apache的WEB根目录下,将etc目录中的所有文件拷贝到根目录下的etc中,最后用浏览器访问你的apache Web服务器即可看到Linux系统的WEB管理界面。 【说明】:编译此源码需要libxml2库的支持 有技术问题可以访问官方网站:http://www.webadminc.com,联系电话:13311223928
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑烯烃快去学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值