服务器编程框架
| 模块 | 单个服务器程序 | 服务器机群 |
|---|---|---|
| I/O处理单元 | 处理客户链接,读写网络数据 | 作为接入服务器,实现负载均衡 |
| 网络存储单元 | 本地数据库、文件或缓存 | 数据库服务 |
| 请求队列 | 各单元之间的通信方式 | 各服务器之间的永久TCP连接 |
请求队列是各单元之间的通信方式的抽象,通常被实现为池的一部分。对于服务器机群而言,请求队列是各台服务器之间预先建立的、静态的、永久的TCP连接。这种TCP连接能提高服务器之间交换数据的效率,因为它避免了动态建立TCP连接导致的额外系统开销。
I/O模型
针对阻塞I/O执行的系统调用可能因为无法立即完成而被操作系统挂起,直到等待事件发生为止。
针对非阻塞I/O执行的系统调用总是立即返回,而不管事件是否已经发生。如果没有发生系统返回-1。此时我们需要通过errno来区分这两种情况。
我们只有在事件已经发生的情况下操作非阻塞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机制则由内核来执行I/O操作(数据在内核缓冲区和用户缓冲区之间的移动是由内核在”后台”完成的。
| I/O模型 | 读写操作和阻塞阶段 |
|---|---|
| 阻塞I/O | 程序阻塞于读写函数 |
| I/O复用 | 程序阻塞于I/O复用系统调用,但可同时监听多个I/O事件。对I/O本身的读写操作是非阻塞的 |
| SIGIO信号 | 信号触发读写就绪事件,用户执行读写操作。程序没有阻塞阶段 |
| 异步I/O | 内核执行读写操作并触发读写完成事件。程序没有阻塞阶段 |
两种高效的事件处理模式
Reactor模式
它要求主线程(I/O处理单元)只负责监听文件描述上是否有是事件发生,有的话立即将该事件通知工作线程。
Proactor模式
与Reactor模式不同,Proactor模式将所有I/O操作都交给主线程和内核来处理,工作线程只负责业务逻辑。
两种高效的并发模式
半同步/半异步模式
半同步/半异步模式中的”同步”和”异步”与之前I/O模型中的”同步”和”异步”是完全不同的概念。在I/O模型中,”同步”和”异步”区分的是内核向应用程序通知的是何种I/O事件(就绪事件还是完成事件),以及该由谁来完成I/O读写(是应用程序还是内核)。在并发模式中,”同步”指的是程序完全按照代码序列的顺序执行;”异步”指的是程序的执行需要由系统事件来驱动。常见的系统事件包括中断、信号等。
| 方式 | 优点 | 缺点 |
|---|---|---|
| 同步 | 逻辑简单 | 效率相对低,实时性差 |
| 异步 | 执行效率高,实时性强 | 编写相对复杂,难于调试和扩展,不适合大量并发 |
因此使用半同步/半异步模式来实现,将结合两者的优点。
其中同步线程用于处理客户逻辑的,异步线程用于处理I/O事件。
本文深入探讨服务器编程框架的构成,包括服务器机群、I/O处理单元等关键组件,并阐述了不同I/O模型的特点及应用场景。此外,还介绍了Reactor与Proactor两种高效事件处理模式,以及半同步/半异步并发模式的优势。
901

被折叠的 条评论
为什么被折叠?



