8 高性能服务器程序框架

8.1 服务器模型

c/s模型

p2p模型

实际使用的P2P模型通常带有一个专门的发现服务器,提供查找服务

8.2 服务器编程框架

I/O处理单元是服务器管理客户连接的模块

一个逻辑单元通常是一个进程或线程,服务器通常由多个逻辑单元,实现对多个客户任务的并行处理

8.3 I/O模型

socket在创建的时候是默认阻塞的,可以通过给socket系统调用的第二个参数传递SOCK_NONBLOCK标志,或者通过fcntl系统调用的F_SETEL命令,将其设置为非阻塞的

针对阻塞I/O执行的系统调用可能因为无法立即完成而被操作系统挂起,可能被阻塞的系统调用包括accept send recv connect

针对非阻塞I/O执行的系统调用总是立即返回

非阻塞I/O通常要和其他I/O通知机制一起使用,比如I/O复用和SIGIO信号

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/O完成事件

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

服务器通常处理三类事件:I/O事件  信号事件  定时事件

同步I/O模型通常用于实现reactor模式  异步I/O模型通常用于实现proactor模式

reactor模式

同步IO模型(以epoll_wait为例)实现的Reactor模式的工作流程:

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

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

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

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

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

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

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

工作线程从队列中取出事件后,将根据事件是可读或可写执行读写数据和处理请求的操作。因此,在Reactor模式中,没必要区分所谓的“读工作线程”和“写工作线程”。

proactor模式

与Reactor模式不同,Proactor模式将所有IO操作都交给主线程和内核来处理,工作线程仅仅负责业务逻辑。

(以aio_read和aio_write为例)工作流程:
1. 主线程调用aio_read函数向内核注册socket上的读完成事件,并告诉内核用户读缓冲区的位置,以及读操作完成时如何通知应用程序(这里以信号为例,详情sigevent的man手册)
2. 主线程继续处理其他逻辑。
3. 当socket上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据已经可用。
4. 应用程序预先定义好的信号处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求之后,调用aio_write函数向内核注册socket上的写完成事件,并告诉内核用户写缓冲区位置,以及写操作完成时如何通知应用程序(仍以信号为例)
5. 主线程继续处理其他逻辑。
6. 当用户缓冲区的数据被写入socket之后,内核将向应用程序发送一个信号,以通知应用程序数据已经发送完毕。
7. 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭socket.

模拟proactor模式

主线程执行数据读写,主线程想工作线程通知完成事件

1. 主线程往epoll内核事件表中注册socket上的读就绪事件。
2. 主线程调用epoll_wait等待socket上有数据可读。
3. 当socket上有数据可读时,epoll_wait通知主线程。主线程从socket循环读取数据,知道没有更多数据可读,然后将读取到的数据封装成一个请求对象并插入到请求队列。
4. 睡眠在请求队列上的某个工作线程被唤醒,它获得请求对象并处理客户请求,然后网epoll内核事件表中注册socket上的写就绪事件。
5. 主线程调用epoll_wait等待socket可写。
6.0当socket可写时,epoll_wait通知主线程。主线程网往socket上写入服务器处理客户端请求的结果。

8.5 两种高效的并发模式

并发编程的目的是让程序同时执行多个任务,适合I/O密集型,不适合计算密集型

半同步半异步模式

这里的“同步”和“异步”和前面的IO的“同步”“异步”是完全不同的概念。在IO模型中,“同步”和“异步”区分的是内核向应用程序通知的是何种IO事件(是就绪事件还是完成事件),以及该由谁来完成IO读写(是应用程序还是内核)。

在并发模式中,“同步”指的是程序完全按照代码序列的顺序执行;“异步”指的是程序的执行需要由系统事件来驱动。常见的系统事件包括中断、信号等。

显然异步线程的执行效率高,实时性强,是很多嵌入式系统采用的模型。但编写异步方式执行的程序相对复杂,难于调试和扩展,而且不适合于大量的并发。而同步线程则相反,它虽然效率相对较低,实时性较差,但逻辑简单。

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

缺点:

1. 主线程和工作线程on共享请求队列,主线程往请求队列添加任务和工作线程从请求队列取出任务都需要给队列加锁

2. 每个工作线程同一时间只能处理一个客户请求,工作线程的切换将耗费大量CPU时间

一种高效的半同步/半异步模式(nginx应该是这种模式)

它每个工作线程能同时处理多个客户连接,主线程只管监听socket,连接socket由工作线程来管理

时间: 2024-08-24 18:33:06

8 高性能服务器程序框架的相关文章

《Linux高性能服务器编程》学习总结(八)——高性能服务器程序框架

第八章      高性能服务器程序框架 我们将服务器一般分为三个主要模块,I/O处理单元.逻辑单元及存储单元.常用的服务器模型有C/S模型和P2P模型,比较简单.我们来看一下网络编程中的I/O模型.首先我们要了解阻塞模型和非阻塞模型的区别,socket在创建时默认是阻塞的,可以在socket系统调用的第二个参数传递SOCK_NONBLOCK标志或者通过fcntl将其设置为非阻塞,针对阻塞I/O的系统调用可能因为无法立即完成而被系统挂起,直到等待的事件发生为止,而非阻塞I/O的系统调用则会立即返回

高性能服务器程序框架

服务器解构为三个主要模块: IO处理单元.四种IO模型和两种高效事件处理模式. 逻辑单元.两种高效并发模式. 存储单元.(暂不讨论) 1.服务器模型 (1)C/S (客户端/服务器)模型 C/S模型的逻辑很简单.服务器启动后,首先创建一个或者多个监听socket,并调用bind函数将其绑定到服务器感兴趣的端口上,然后调用listen函数等待客户连接.服务器稳定运行后,客户端就可以调用Connect函数向服务器发起连接了.由于客户连接请求时随机到达的异步事件,服务器需要使用某种I/O模型来监听到连

完成端口与高性能服务器程序开发

原文出处:http://blog.csdn.NET/roen/archive/2007/03/19/1533378.aspx 以一个文件传输服务端为例,在我的机器上它只起两个线程就可以为很多个客户端同时提供文件下载服务,程序的性能会随机器内CPU个数的增加而线性增长,我 尽可能做到使它清晰易懂,虽然程序很小却用到了NT 5的一些新特性,重叠IO,完成端口以及线程池,基于这种模型的服务端程序应该是NT系统上性能最好的了. 首先.做为完成端口的基础,我们应该理解重叠IO,这需要你已经理解了内核对象及

协作半驻留式服务器程序开发框架 --- 基于 Postfix 服务器框架改造

一.概述 现在大家在和Java, PHP, .net写应用程序时,都会用到一些成熟的服务框架,所以开发效率是比较高的.而在用C/C++写服务器程序时,用的就五花八门了,有些人用ACE, 有些人用ICE(号称比ACE强许多),等等,这类服务器框架及库比较丰富,但入门门槛比较高,所以更多的人是自己直接写服务器程序,初始写时觉得比较简 单,可时间久了,便会觉得难以扩展,性能低,容易出错.其实,Postfix 作者为我们提供了一个高效.稳定.安全的服务器框架模型,虽然Postfix主要用作邮件系统的 m

SuperSocket框架学习笔记2-构建SuperWebSocket服务器程序

SuperSocket框架学习笔记2-构建SuperWebSocket服务器程序 上一节简单介绍了 基本的SuperSocket服务器 这一节我们使用 SuperWebSocket构建一个 能与Unity3D通信的(Console控制台)服务器程序 嘎嘎 先下载   需要的  DLL类库 服务端: SuperSocket1.6.1 这个必备 http://www.supersocket.net/ SuperWebSocket 服务端必备 http://superwebsocket.codeple

《Linux高性能服务器编程》学习总结(七)——Linux服务器程序规范

第七章      Linux服务器程序规范 服务器程序除了需要网络通信外,还应该考虑很多其他的细节,而这些细节很多很杂,但又基本是模板式的.1)服务器程序基本都是以后台形式运行的,没有控制终端,不能接受用户输入,其父进程通常是init.2)服务器程序有一套日志系统.3)服务器程序以某个专门的非root身份运行.4)服务器通常是可配置的.5)服务器进程启动时通常会生成一个PID文件以记录后台进程的PID.6)服务器程序同城需要考虑系统资源和限制. 服务器一般使用syslog函数与rsyslogd守

LINUX高性能服务器读书笔记之程序规范

背景:除了网络通信,服务器程序还有许多细节问题,.特点:细节都是模板式的,所以只需要讲明白就好,遵循一定的规范就好类别:1.1运行形式-->后台进程,又称为守卫进程.没有控制终端,也不会意外受到用户输入.它的父进程是:init进程(pid是1 的进程)1.2日志系统.一般至少输出到文件,还可以输出到专门的UDP服务器.一般在/var/log 都拥有自己的日志目录1.3运行身份:某个专门的非root身份.例子:mysqld,httpd,syslogd等后台程序,都分别拥有自己的账户mysql,ap

高性能服务器架构思路

在服务器端程序开发领域,性能问题一直是备受关注的重点.业界有大量的框架.组件.类库都是以性能为卖点而广为人知.然而,服务器端程序在性能问题上应该有何种基本思路,这个却很少被这些项目的文档提及.本文正式希望介绍服务器端解决性能问题的基本策略和经典实践,并分为几个部分来说明: 1. 缓存策略的概念和实例 2.缓存策略的难点:不同特点的缓存数据的清理机制 3.分布策略的概念和实例 4.分布策略的难点:共享数据安全性与代码复杂度的平衡 缓存 缓存策略的概念 我们提到服务器端性能问题的时候,往往会混淆不清

【转】高性能服务器架构(High-Performance Server Architecture)

High-Performance Server Architecture 高性能服务器架构 来源:http://pl.atyp.us/content/tech/servers.html译文来源:http://www.lupaworld.com/home/space-341888-do-blog-id-136718.html (map注:本人看了一遍,“于我心有戚戚焉”,翻译得也很好,于是整理了一下,重新发布,备忘) 引言 本文将与你分享我多年来在服务器开发方面的一些经验.对于这里所说的服务器,更