Reactor模式和Proactor模式
Reactor
- 主线程往epoll内核事件表中注册socket上的读就绪事件
- 主线程调用epoll_wait等待socket上有数据可读
- 当socket上有数据可读时,epoll_wait通知主线程,主线程则将socket可读事件放入请求队列。
- 睡眠在请求队列上的某个工作线程被唤醒,它从socket读取数据,并处理客户请求,然后往epoll内核事件表中注册该socket上的写就绪事件。
- 主线程调用epoll_wait等待socket可写
- 当socket可写时,epoll_wait通知主线程,主线程将socket可写事件放入请求队列
- 睡眠在请求队列上的某个工作线程(工作线程从请求队列读取事件后,根据事件的类型来决定如何处理它,没有必要区分读工作线程和写工作线程)被唤醒,它往socket上写入服务器处理客户请求的结果
Reactor模式的缺点:
Reactor处理耗时长的操作(如文件I/O)会造成事件分发的阻塞,影响到后续事件的处理。
因此涉及到文件I/O相关的操作,需要使用异步I/O,即使用Proactor模式效果更佳。
redis采用的就是reactor模型https://www.xilidou.com/2018/03/22/redis-event/
Proactor
- 主线程调用aio_read向内核注册socket上的读完成事件,并告诉内核用户缓冲区的位置,以及读操作完成时如何通知应用程序(可以用信号)
- 主线程继续处理其他逻辑
- 当socket上的读数据被读入用户缓冲区后,内核向应用进程发送一个信号,已通知应用程序数据已经可用
- 应用进程预先定义好的信号处理函数选择一个工作线程来处理处理客户请求,工作线程处理完客户请求之后,调用aio_write向内核注册socket的完成写事件,并告诉内核用户写缓冲区的位置,以及操作完成时如何通知应用程序(可以用信号)
- 主线程继续处理其他逻辑
- 当用户缓冲区的数据被写入socket之后,内核将向应用程序发送一个信号,已通知应用程序数据已经发送完毕
- 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭socket
参考资料: