Web 服务核心模型
Apache 的三种工作模式
Apache 作为老牌 Web 服务器,其多进程模型在不同场景下表现各异。
prefork 预派生模式
这是最经典的配置。主进程启动多个独立子进程,每个子进程单线程处理请求,底层使用 select 模型。最大并发通常限制在 1024。虽然内存占用较高,但它的稳定性极佳,故障隔离性好,适合访问量中等的场景。不过,由于每个请求对应一个进程,资源开销大,在高并发下显得力不从心。
worker 混合模式 为了解决 prefork 的资源浪费问题,引入了多进程 + 多线程的混合架构。主进程管理子进程,子进程内包含固定数量的线程池。相比 prefork,它显著降低了内存占用,支持更高并发。但在长连接(keepalive)场景下,线程若长期被占用,高并发时容易出现无可用线程的情况。
event 事件驱动模型
从 2.4.X 版本开始正式支持,基于 epoll 机制。它专门解决 keepalive 连接空占线程的问题:只有真实请求时才分配服务线程,执行完立即释放。单线程响应多请求,内存占用少,高并发表现优秀,是 Apache 目前推荐的高性能方案。
Nginx 简介与特性
Nginx 由俄罗斯工程师 Igor Sysoev 开发,最初用于 Rambler.ru 搜索引擎。2004 年发布首个稳定版,核心代码约 19.8 万行,以高性能著称。天猫、淘宝、京东等一线互联网公司均在其生产环境中广泛使用或二次开发。
它不仅是 HTTP 服务器,还支持反向代理、邮件服务器等功能。1.9 版本以上开启 stream 模块后,更支持 TCP/UDP 负载均衡。其核心优势在于快速响应静态网页请求,并原生支持 FastCGI、SSL、URL Rewrite 及 Gzip 压缩等高级功能。
服务端 I/O 流程解析
基本概念与类型
I/O 即输入输出,IOPS 则是衡量磁盘性能的核心指标。完整的 I/O 过程涉及用户空间进程与内核空间的数据交换。由于内核与用户空间严格隔离,数据必须经过拷贝才能完成交互。
- 磁盘 I/O:进程发起系统调用,内核加载文件到内存缓冲区,再拷贝至进程内存。大文件加载耗时较长。
- 网络 I/O:本质是对 socket 文件的读写,涉及网络协议栈与用户空间进程的数据交换。
通用流程分为两个阶段:首先是数据准备(内核加载),其次是数据拷贝(内核到用户)。这两个阶段的耗时占比往往决定了整体性能。
同步与异步、阻塞与非阻塞
理解 I/O 模型的关键在于区分两组概念:
- 同步 vs 异步:关注消息通信机制。同步模式下,被调用者不主动通知结果,需调用者查询;异步模式下,被调用者通过状态或回调主动告知运行状态。
- 阻塞 vs 非阻塞:关注等待结果时的状态。阻塞操作完成后才返回,调用者挂起;非阻塞操作立即返回状态值,调用者可继续执行其他任务。
五种网络 I/O 模型对比
1. 阻塞型 I/O (Blocking IO)
用户线程发起 read 调用后,会一直等待数据包到达并完成拷贝,期间 CPU 利用率低。优点是程序简单,缺点是每连接需独立线程,高并发时内存和切换开销巨大。Apache prefork 模式即基于此原理。
2. 非阻塞型 I/O (Nonblocking IO)
IO 调用后立即返回,若无数据则返回错误码(如 EWOULDBLOCK)。用户线程需不断轮询直到数据就绪。这避免了阻塞,但大量文件描述符的轮询会导致上下文切换频繁,且轮询间隔难把控,实际极少单独使用。
3. 信号驱动式 I/O (Signal-driven IO)
注册信号处理回调函数,内核数据就绪时发送 SIGIO 信号触发回调。等待期间进程不阻塞,资源利用率高。但缺点是信号队列可能溢出导致通知失效,适用于特定场景。
4. 异步 I/O (Asynchronous IO)
这是 POSIX 标准定义的真正异步。用户调用 aio_read 后立即返回,内核完成数据准备和拷贝后才通知用户进程。IO 两个阶段进程均非阻塞,充分利用 DMA 特性。但操作系统实现复杂,Linux 2.6 才引入,常依赖 libevent/libuv 等库封装。

