高性能服务器程序框架

服务器可以分为三个模块:I/O处理单元,逻辑单元,存储单元。

服务器模型

C/S

逻辑
服务器启动后,首先创建一个或多个socket,并调用bind函数将其与端口绑定,使用listen函数等待客户端链接。
客户端调用connect函数向服务器发起连接(注意:这是三次握手发生阶段)。但是客户端的连接是随机到达的异步事件,服务器需要使用I/O模型来监听这一事件。
TCP服务器和客户端的工作流程
当监听到连接请求后,服务器调用accept接受该请求,并分配一个逻辑单元为新的连接服务。逻辑单元可以是新建的子进程、子线程或其他。逻辑单元读取客户请求并处理,返回处理结果给客户。
服务器在处理一个客户的请求时,还会监听其他客户的请求。

P2P

服务器框架

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

  • I/O处理单元:管理客户连接的模块。负责等待并接受新的客户连接,接受客户数据,将服务器的响应数据返回给客户。但是数据的收发并不一定在I//O处理单元中执行,也有可能在逻辑单元执行(取决于事件处理模式)。
  • 逻辑单元:通常是一个进程或线程,分析并处理客户数据,然后将结果传递给I/O处理单元或直接发给客户端(取决于事件模式)。
  • 网络存储单元:数据库、缓存、文件等,但不是必须的。
  • 请求队列:单元之间通信方式的抽象,通常实现为池的形式。

I/O模型

阻塞和非阻塞的概念可以应用于所有的文件描述符,而非仅限于socket。称阻塞的文件描述符为阻塞I/O,非阻塞的文件描述符为非阻塞I/O。
阻塞I/O时,执行系统调用可能因为无法完成而被操作系统挂起。socket编程中可能会挂起的操作:connect,send,recv,accept。
非阻塞I/O时,系统调用立即返回,不论事件是否发生。没有发生就返回-1,并设置errno。可以查看errno区分情况。非阻塞I/O需要和I/O通知机制一起使用,如I/O复用SIGIO信号

I/O复用

应用程序通过I/O复用函数在内核注册一组事件,内核通过I/O复用函数把就绪事件通知给程序,如select,poll,epoll。
注意,I/O复用函数本身是阻塞的,它们是高效的原因是因为它们具有同时监听多个I/O事件的能力。

SIGIO信号

可以报告I/O事件,可以为一个目标文件符指定宿主进程,那么被指定的宿主进程将捕获到SIGIO信号。当目标文件符上有事件发生时,SIGIO信号的信号处理函数将被触发。

阻塞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/O由内核完成。

事件处理模式

Server通常需要处理I/O事件,信号以及定时事件。有两种事件处理模式,Reactor和Proactor。
同步I/O模型常用于实现Reactor模式,异步I/O模型实现Proactor模式,但是可以用同步I/O方式模拟。

Reactor

总体:要求主线程(I/O处理模块)监听文件描述符上是否有事件发生,如果有,那么立即将该事件通知工作线程(逻辑处理单元),除此,主线程不负责其他任何工作。数据的读写,新连接的接受都在工作线程中完成。
以epoll为例,Reactor模型的工作流程是:

  • 主线程在epoll内核事件表中注册socket上的读就绪事件
  • 主线程调用epoll_wait等待socket上有数据可读
  • socket上有数据可读时,epoll_wait通知主线程,主线程将socket可读事件插入到请求队列
  • 睡眠在请求队列的工作线程被唤醒,它从socket读取数据并处理客户请求,然后在epoll内核事件表中注册该socket的写就绪事件
  • 主线程调用epoll_wait等待socket可写
  • 当socket可写时,epoll_wait通知主线程,主线程将socket可写事件放入请求队列
  • 睡眠在请求队列上的某个工作线程被唤醒,它往socket上写入服务器处理客户请求的结果
    在这里插入图片描述

Proactor模式

Proactor模式将所有的I/O操作都交给主线程和内核处理,工作线程进处理业务逻辑。
在这里插入图片描述

同步I/O模拟Proactor

主线程执行数据读写操作,读写完成后,主线程向工作线程通知完成事件,工作线程直接获得了读写的结果,只需完成逻辑处理。
工作流程如下:

  • 主线程在epoll内核事件表注册socket上的读就绪事件
  • 主线程调用epoll_wait等待socket上有数据可读
  • 当socket上有数据可读时,epoll_wait通知主线程。主线程从socket循环读取数据至无数据可读,将读取到的数据封装成一个请求对象并插入到请求队列
  • 睡眠在请求队列的工作线程被唤醒,获得请求对象并处理客户请求,然后往epoll内核事件表中注册socket的写就绪事件
  • 主线程调用epoll_wait等待socket可写
  • socket可写时,epoll_wait通知主线程,主线程往socket上写入服务器处理客户请求的结果
    在这里插入图片描述

并发模式

并发模式是指I/O处理单元和多个逻辑处理单元之间协调完成任务的方法。

半同步/半异步模式

与I/O的同步区分,I/O的同步是指内核向应用程序通知的何种IO事件(就绪事件还是完成事件)。并发同步是指程序按照代码顺序执行,异步是指程序的执行需要系统事件驱动(中断、信号等)
在这里插入图片描述
在半同步半异步模式中,同步线程处理客户逻辑,异步线程处理IO事件。异步线程监听到客户请求后,将其封装成请求对象插入到请求队列,请求队列通知同步模式下的工作线程,读取并处理该对象。
在这里插入图片描述
半同步半异步的变体,半同步半反应堆模式 。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

领导者追随者模式

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值