第八章 高性能服务器框架

服务器一般可以解构为三个主要模块

  • I/O处理单元:四种I/O模型,两种高效时间处理模式
  • 逻辑单元:两种高效并发模式,逻辑状态机
  • 存储单元:服务器程序可选模块

8.1 服务器模型

8.1.1 C/S模型

  • C/S(client/server,客户/服务器模型)。
  • 逻辑:服务器启动,创建一个或多个监听socket,调用bind函数绑定到特定端口,调用listen函数等待客户连接。客户端可以调用connect函数像服务器发起连接。
  • 因为客户端的连接请求是随机到达的异步事件,需要某种I/O模型来监听这一事件。
    在这里插入图片描述

8.1.2 P2P模型

  • 所有主机地位对等,每台机器在消耗服务的同时,也给其他机器提供服务。
  • 传统的P2P模型主机之间很难发现,所以P2P模型通常有一个发现服务器,专门用来提供给查找服务,使得客户能够很快找到自己的资源。
    在这里插入图片描述

8.2 服务器编程框架

在这里插入图片描述

  • I/O处理单元:
    • 管理客户连接模块。
    • 等待并接收新的客户连接
    • 接收客户数据
    • 将服务器响应返回给客户端
    • 数据的收发也可能在逻辑单元中执行。
  • 逻辑单元:
    • 通常是一个进程或线程
    • 分析并处理客户数据,结果传递给I/O处理单元或直接发送给客户端。
    • 对于多个逻辑单元的服务器,可以实现并行处理。
  • 存储单元:
    • 数据库、缓存、文件、独立的服务器
    • 并不是必须的。例如ssh和telnet就不需要
  • 请求队列:
    • 各个单元之间通信方式的抽象。
    • I/O处理单元接收到客户请求时,需要以某种方式通知逻辑单元来处理请求。
    • 多个逻辑单元访问一个存储单元时,也需要以某种机制协调处理静态条件。
    • 请求队列通常被实现为池的一部分。

在这里插入图片描述
在这里插入图片描述

8.3 I/O模型

  • socket创建时默认是阻塞的。
  • 阻塞的文件描述符称为阻塞I/O,非阻塞文件描述符称为非阻塞I/O。
  • 针对阻塞I/O的系统调用可能因为无法立刻完成被系统挂起,直到等待的事件发送。
    • 例如客户端的connect调用,如果服务器的确认文报没有到达客户端,那么connect将会被挂起,直到客户端收到确认文报唤醒。
    • accept、send、recv和connect系统调用都可能会被阻塞。
  • 对于非阻塞I/O的系统调用会立刻返回,不管事件是否发送,如果没发送,返回-1。
  • 在事件已经发生的情况下操作非阻塞I/O才能提高程序效率。因此非阻塞I/O通常要和其他I/O通知机制一起使用。
  • I/O复用
    • 应用程序通过I/O复用函数向内核注册一组事件,内核通过I/O复用函数把其中就绪的 + 事件通知给应用程序。
    • Linux常用I/O复用函数是select、poll、epoll_wait
    • I/O复用本身是阻塞的,因为他们可以同时监听多个I/O事件,所以才提高效率。
    • 阻塞I/O,I/O复用,型号驱动I/O都是同步I/O模型。I/O的读写操作,都是在I/O事件发生后,由应用程序来完成。
    • 对于异步I/O而言,用户可以直接对I/O执行读写操作。
    • 同步I/O向应用程序通知的是I/O就绪事件,异步I/sO向应用程序通知的是I/O完成事件。

在这里插入图片描述

8.4 两种高效的事件处理模式

服务器程序主要处理三类事件:

  • I/O事件
  • 信号事件
  • 定时事件

Reactor和Proactor

  • 同步I\O模型通常用于事件Reactor模式
  • 异步I\O通常用于实现Proactor模式,但是同步I\O也能实现Proactor模式。

8.4.1 Reactor模式

  • 主线程(I/O处理单元)只负责监听事件是否发生,事件发生立刻通知到工作线程。
  • 读写数据、接收新连接、处理用户请求均在工作线程完成。
  • 使用同步I/O(例如epoll_wait)实现的Reactor模式:
    • 主线程往epoll内核事件表注册socket可读就绪事件
    • 主线程调用epoll_wait等待socket上有数据可读
    • socket有数据,epoll_wait通知主线程,主线程将socket可读事件放入请求队列。
    • 某个工作线程被唤醒,从socket中读取数据,处理客户请求,往epoll内核事件表注册socket上的写就绪事件。
    • 主线程调用epoll_wait等待socket可写
    • 当socket可写时,epoll_wait通知主线程,主线程将socket可写事件放入请求队列。
    • 某个工作线程被唤醒,往socket写入服务器处理客户请求的结果。
      在这里插入图片描述

8.4.2 Proactor模式

  • Proator模式把所有I/O操作交给主线程和内核处理,工作线程处理逻辑业务。
  • 使用异步I/O(aio_read和aio_write)实现的Proactor模式工作流程:
    • 主线程调用aio_read函数向内核注册socket上的读完成事件,并告诉内核用户读缓冲区的位置,以及读操作完成时候如何通知应用程序。
    • 主线程继续处理其他罗i就
    • 当socket上的数据被读入用户缓冲区后,内核向应用程序发送信号,通知应用程序数据以及可用。
    • 选择一个工作线程处理用户请求。
    • 处理完用户请求,使用aio_write函数向内核注册socket写完成事件,并告诉内核用户写缓冲区的位置,以及写操作完成时如何通知应用程序。
    • 主线程继续处理其他逻辑。
    • 当用户缓冲区的数据被写入socket之后,内核向应用程序发送一个信号,通知应用程序数据发送完毕。
    • 应用程序预先定义好的信号处理函数选择一个工作线程来做善后工作,例如决定是否关闭socket。
      在这里插入图片描述

8.4.3 模拟Proactor模式

  • 使用同步IO也能模拟Proactor模式,原理在于主线程执行数据读写操作,当读写完成后,主线程向工作线程通知完成事件,所以从工作线程角度看,他直接获得了数据读写的结果,只需要对结果进行逻辑处理。
  • 使用同步IO(例如epoll_wait)模拟Proactor模式的工作流程如下:
    • 主线程往epoll内核事件表注册socket 读就绪事件
    • 主线程调用epoll_wait函数等待socket上有数据可读
    • 当socket上有数据可读时,epoll_wait通知主线程,主线程从socket循环读取数据, 将读取到的数据封装成请求并加入请求队列。
    • 请求队列某个工作线程被唤醒,获得请求对象并处理客户请求,之后往epoll内核事件表注册socket写就绪事件、
    • 主线程调用epoll_wait等待socket可写
    • socket可写时,epoll_wait通知主线程,主线程往socket写入处理结果。
      在这里插入图片描述

8.5 两种高效的并发模式

  • 计算密集型,并发编程并无优势,反倒由于任务切换使得效率降低。
  • I/O密集型,并发可以提高CPU利用率。

8.5.1 半同步/半异步模式

  • 同步:程序按代码顺序执行
  • 异步:程序执行需要事件驱动
    在这里插入图片描述

8.5.1.1 半同步/半反应堆 模式

  • 主线程为异步线程,负责监听socket事件
  • 采用Reactor模式,工作线程自己从socket中读取客户请求,以及往socket中写入服务器应答。
  • 也可以采用Proactor模式

缺点

  • 主线程和工作线程共享请求队列,所以主线程加任务到请求队列,或者工作线程从主线程中取出任务,都要加锁解锁。
  • 工作线程只能处理一个客户请求,客户数量多而工作线程少, 客户端响应速度会降低。

相对高效的半同步半异步

  • 主线程监听socket,连接socket有工作线程来处理
  • 与上边的半同步半反应堆的区别在于,上边是在主线程的epoll注册事件,这个是在工作线程epoll注册事件
    在这里插入图片描述

8.5.2 领导者/追随者模式

  • 程序只有一个领导者线程,负责监听IO事件,其他线程是追随者,休眠在线程池中等待成为新的领导者。
  • 如果当前领导者线程检测到IO事件,需要首先从线程池中选出新的领导者线程,如何处理IO事件,新的领导者线程等待新的IO事件,而原来的领导者则处理IO事件, 实现并发。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值