0.简介
本文从一个整体视角来对服务器编程框架来介绍,将其分为三个部分:I/O模型,逻辑处理,持久化存储单元。介绍其三者的关系,同时详细去介绍I/O模型部分及其衍生出的两种并发模型:Reactor和Proactor。
1. 整体框架
服务器本质上是接受请求然后去做相应逻辑处理然后将结果进行返回(需要保存则会进行持久化存储),所以其整体可以分为三部分:I/O部分,逻辑处理部分,持久化存储部分,逻辑单元是业务处理,存储和I/O单元属于基础组件,如下:
2. I/O模型
2.1 同步阻塞I/O(Blocking I/O)
同步阻塞I/O意味着I/O操作的发起者(通常是应用程序)会等待I/O操作完成,然后才会继续执行后续的代码。换句话说,同步I/O会阻塞程序的执行,直到I/O操作完成。其特点就是阻塞且顺序执行。
其实现方式比较简单,默认的就是该方式,比如默认创建出的socket就是同步阻塞的。
2.2 同步非阻塞I/O(Non-blocking I/O)
当应用程序发起一个I/O操作时,如果操作不能立即完成,操作系统会立即返回一个错误状态,而不是阻塞线程。应用程序可以继续执行其他任务,或者定期重试I/O操作,直到它完成。其特点是不会一直等待,可以在未完成等待期间处理其他事情,但需要轮询状态。
其实现方式,可以将对应的描述符通过fcntl函数的F_SETFL命令设置,或者在socket创建时增加SOCK_NONBLOCK标志。
2.3 I/O多路复用(I/O Multiplexing)
I/O复用允许单个线程或进程监视多个文件描述符(如socket),一旦某个文件描述符就绪,对应的操作就可以执行。这通常是通过select、poll或epoll等系统调用实现的。其特点是可以通过一个系统调用去监视多个文件描述符的状态,只处理就绪的部分。
其常见的实现方式是通过select/poll/epoll,通过将文件描述符传递进去让内核负责检测其状态,然后达到同时管理多个的目的。
2.4 异步I/O(Asynchronous I/O)
应用程序发起一个I/O请求后,不必等待I/O操作完成即可继续执行其他任务。当I/O操作完成时,系统会通知应用程序,或者调用应用程序注册的回调函数来处理I/O事件。其特点是没有阻塞阶段,所有阻塞的内容都异步交给内核去执行。
其常见的实现方式有,通过aio的接口去实现或者通过信号机制(发送SIGIO信号)去实现。
3. 并发模型
3.1 Reactor模式
Reactor模式,也称发布者模式或通知者模式,是一种同步非阻塞的事件处理模式。它将I/O操作的事件管理与实际的I/O操作分离(也就是主线程只负责监听文件描述符上是否有事件发生,有的话就通知工作线程去处理,主线程只负责管理,而不负责实际操作)。
3.2 Proactor模式
Proactor模式是一种异步非阻塞的事件处理模式。与Reactor模式不同,Proactor模式中I/O操作由主线程和操作系统内核完成,工作线程只负责业务逻辑。其核心思想是应用程序只需要提供回调函数并提交异步I/O操作,剩下的由操作系统负责。当I/O操作完成时,操作系统调用回调函数处理结果。
3.3 对比
1)事件处理方式:Reactor模式是同步非阻塞的,由应用程序主动发起I/O操作并处理事件;而Proactor模式是异步非阻塞的,I/O操作由操作系统完成,应用程序只处理操作结果。
2)编程复杂度:Reactor模式需要开发者手动管理I/O的状态和调用相应的操作,编程复杂度较高;而Proactor模式简化了I/O操作的处理流程,但管理异步任务的调度和完成事件仍然较为复杂。
3)对操作系统的依赖:Reactor模式通常依赖于select、poll、epoll等I/O多路复用机制来实现事件的监听和分发;而Proactor模式需要操作系统原生支持异步I/O机制。
4)应用场景:Reactor模式常用于高并发、高性能的服务器架构中;而Proactor模式则更适用于需要高效处理异步I/O操作的场景,如Windows平台下的I/O完成端口(IOCP)。