nginx采用单进程事件驱动模型,一个worker可处理万级并发连接,内存平稳;apache prefork模式为每个连接分配独立进程,内存随并发线性增长,高并发易触发503。

核心区别在于:Nginx 用**一个进程+事件驱动**应对成千上万连接,Apache(尤其 prefork 模式)是**一个连接就占一个进程**,资源消耗随并发线性增长。
连接处理方式完全不同
Apache prefork 模式下,每个新连接到来,主进程会 fork 出一个新子进程专门服务它。这个进程全程阻塞——调用 recv() 等数据时挂起,读完解析再调用 send() 又等发完,中间不能干别的。哪怕客户端只发了半截请求、或启用了 Keep-Alive 空等,该进程就一直占着内存和 CPU 调度时间。
Nginx 不 fork 新进程。它的每个 worker 进程启动后,就注册监听 socket 到 epoll,并进入一个循环:不断检查“哪些连接有新数据可读”“哪些响应已准备好可写”。只要内核通过 epoll 通知“某连接有数据来了”,worker 就立刻去读;读完不等磁盘 I/O 完,而是把读到的内容暂存,转头处理下一个就绪事件;等磁盘返回数据后,epoll 再次通知,它才继续拼响应、发回客户端。
资源开销差异巨大
- Apache 启动 1000 个并发连接,可能就要运行 1000 个进程——每个进程至少占用几 MB 内存,CPU 频繁在它们之间切换,上下文开销飙升
- Nginx 默认只启 4 个 worker(通常等于 CPU 核数),每个 worker 能同时管理上万连接。没有额外进程创建/销毁成本,也没有线程间同步锁的争抢
- 内存里没有重复的配置副本、日志缓冲区或模块实例,worker 共享 master 加载的配置和静态资源缓存
IO 模型决定响应节奏
Apache 的 IO 是同步阻塞:必须等 recv 完、open 完、send 完,才能推进下一步。整个请求生命周期被绑死在一个执行流里。
Nginx 的 IO 是异步非阻塞:发起 recv 后立即返回,去做别的事;发起 open 后不等磁盘,先处理其他连接;send 调用后只管注册写就绪事件,结果由后续事件触发。所有耗时操作都让出 CPU,靠 epoll 的就绪通知来驱动下一步——这就是“事件循环”的实质。
稳定性与适用场景倾向不同
Apache 的隔离性更强:某个 PHP 脚本崩溃,最多干掉一个进程,不影响其他请求。适合对单请求逻辑复杂、执行时间长、且难以做异步改造的传统应用。
Nginx 的轻量和高并发能力突出,但所有请求共享同一个 worker 进程地址空间。一旦某个模块出严重错误(如 C 模块内存越界),整个 worker 可能退出。因此它更适合作为反向代理、静态资源服务或与 FastCGI/HTTP 后端解耦协作,把动态逻辑交给专用服务处理。











