高性能服务器笔记

事件处理模型

Reactor模型

Reactor是处理并发一种常用模式,用于同步 I/O,主要的思想是要求主线程只负责监听文件描述是否有事件发生,如果有,就将该事件通知工作线程。除此之外主线程不做其他工作,读写数据,接受新的连接,以及处理客户的请求都是在工作线程中完成。

使用同步I/O模型实现Reactor模式的工作流程:

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

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

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

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

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

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

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

reactor.jpg

Proactor 模型

与Reactor模型不同,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.jpg

并发模式

半同步/半异步(Half-Sync/Half-Async)模式

在半同步/半异步的模式中,同步线程处理客户的逻辑,异步线程处理I/O事件,异步线程监听到客户请求后,就将其封装成请求对象并插入请求队列中。请求队列将通知某个工作线程在同步模式的工作线程来读取并处理该请求的对象。具体选择哪个工作线程来为新的客户请求服务,则取决于请求队列的设计。比如最简单的轮流选取工作线程的Round Robin算法。
hsha.jpg

领导者/追随者(Leader/Followers)模式

领导者/追随者模式是多个工作线程轮流获得事件源集合,轮流监听,分发并发事件的一种模式。在任意时间点,程序都仅有一个领导者,它负责监听I/O事件。而其他的线程作为追随者,它们休眠在线程池中等待称为新的领导者。当前的领导者如果检测到I/O事件,首先要从线程池中推选出新的领导者线程,然后处理I/O事件,此时,新的领导等待新的I/O事件,而原来的领导者则处理I/O事件,二者实现了并发。
leader-follower.jpg

参考《Linux高性能服务器编程》

添加新评论