NGINX 在 Web 性能方面表现出色,关键在于软件的设计方式。许多 Web 服务器和应用服务器采用简单的线程式或进程式架构;NGINX 则采用复杂的事件驱动架构,使其能在现代硬件上扩展到数十万条并发连接。
NGINX 架构信息图从高层进程架构逐步深入,展示 NGINX 如何在单个进程中处理多个连接。本文进一步解释它的运作方式。
先看整体:NGINX 的进程模型

要理解这个设计,首先需要知道 NGINX 怎样运行。NGINX 有一个主进程,负责读取配置、绑定端口等需要特权的操作,还包含若干工作进程和辅助进程。
# service nginx restart
* Restarting nginx
# ps -ef –forest | grep nginx
root 32475 1 0 13:36 ? 00:00:00 nginx: master process /usr/sbin/nginx
-c /etc/nginx/nginx.conf
nginx 32476 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32477 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32479 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32480 32475 0 13:36 ? 00:00:00 _ nginx: worker process
nginx 32481 32475 0 13:36 ? 00:00:00 _ nginx: cache manager process
nginx 32482 32475 0 13:36 ? 00:00:00 _ nginx: cache loader process
在这台四核服务器上,NGINX 主进程创建了四个工作进程,以及两个管理磁盘内容缓存的辅助进程。
为什么架构很重要?
Unix 应用的基本执行单元是线程或进程。从 Linux 操作系统的角度看,二者大体相似,主要差别是共享内存的程度。线程或进程包含一组独立指令,操作系统可以把它调度到某个 CPU 核心上执行。多数复杂应用同时运行多个线程或进程,原因有两个:
- 能够同时利用更多计算核心。
- 线程和进程让并行操作很容易实现,例如同时处理多个连接。
进程和线程会消耗资源:各自需要内存和其他操作系统资源,还要被换入、换出 CPU 核心,这一操作称为上下文切换。多数现代服务器可以同时处理数百个小型活跃线程或进程,但内存耗尽,或者高 I/O 负载导致大量上下文切换时,性能就会严重下降。
设计网络应用的一种常见方式,是为每个连接分配一个线程或进程。这种架构简单、容易实现,但应用需要处理数千条同时连接时,便难以扩展。
NGINX 怎样工作?
NGINX 使用可预测的进程模型,并根据可用硬件资源进行调优:
- 主进程(master)负责读取配置、绑定端口等特权操作,然后创建少量子进程,即下面三类进程。
- 缓存加载进程(cache loader)在启动时运行,把磁盘缓存的信息加载到内存,然后退出。它采用保守的调度方式,资源需求较低。
- 缓存管理进程(cache manager)定期运行,清理磁盘缓存条目,让缓存保持在配置的大小范围内。
- 工作进程(worker)承担实际工作:处理网络连接、读写磁盘内容、与上游服务器通信。
多数场景下建议每个 CPU 核心运行一个工作进程,以高效利用硬件。可以把 worker_processes 指令设置为 auto:
worker_processes auto;
NGINX 服务活跃时,忙碌的主要是工作进程。每个工作进程以非阻塞方式处理多个连接,减少上下文切换次数。
每个工作进程都是单线程、独立运行的,接收并处理新连接。进程之间可以通过共享内存交换缓存数据、会话保持数据和其他共享资源。
深入 NGINX 工作进程

每个 NGINX 工作进程都使用 NGINX 配置进行初始化,并由主进程提供一组监听套接字。
工作进程首先等待监听套接字上的事件(相关机制包括 accept_mutex 和内核套接字分片)。新连接进入时会产生事件。这些连接会被交给状态机:HTTP 状态机最常用,NGINX 也为 stream(原始 TCP)流量以及 SMTP、IMAP、POP3 等邮件协议实现了状态机。

状态机本质上是一组告诉 NGINX 如何处理请求的指令。多数提供类似功能的 Web 服务器也使用相似的状态机,区别在于实现方式。
调度状态机
可以把状态机想象成国际象棋的规则,每个 HTTP 事务是一盘棋。棋盘的一边是 Web 服务器:一位能迅速作出决策的特级大师;另一边是远程客户端,也就是通过相对缓慢的网络访问网站或应用的浏览器。
不过,规则可能相当复杂。例如,Web 服务器可能需要与其他参与者通信,代理请求到上游应用,或与认证服务器交互。服务器里的第三方模块甚至能够扩展这盘棋的规则。
阻塞式状态机
前面把进程或线程描述为一组独立指令,操作系统能将它调度到 CPU 核心上执行。多数 Web 服务器和 Web 应用使用“一连接一进程”或“一连接一线程”的模型下棋。每个进程或线程包含把一盘棋下到结束的指令。在服务器执行它的时间里,它大部分时候处于阻塞状态,等待客户端走出下一步。

- Web 服务器进程在监听套接字上等待新连接,也就是客户端发起新棋局。
- 收到新棋局后,它开始下棋,每走一步就阻塞,等待客户端回应。
- 一盘棋结束后,进程可能等待客户端是否要开始新棋局,这相当于 keepalive 连接。若连接关闭(客户端离开或发生超时),服务器进程重新回去等待新棋局。
关键在于,每条活跃 HTTP 连接,也就是每盘棋,都需要一个专用进程或线程,也就是一位特级大师。架构简单,容易通过第三方模块增加“新规则”。但它极不均衡:仅由文件描述符和少量内存表示的轻量 HTTP 连接,被映射成一个独立线程或进程——非常重量级的操作系统对象。它方便编程,却浪费大量资源。
NGINX 是真正的特级大师
你可能听过同时对弈:一位国际象棋特级大师同时与几十位对手下棋。

NGINX 工作进程就是这样“下棋”的。每个工作进程——记住,通常每个 CPU 核心对应一个——都像一位特级大师,可以同时进行数百盘、实际上数十万盘棋。

- 工作进程等待监听套接字和连接套接字上的事件。
- Events occur on the sockets and the worker handles them:
- 监听套接字上的事件意味着客户端开始了新棋局,工作进程会创建新的连接套接字。
- 连接套接字上的事件意味着客户端走了一步,工作进程迅速回应。
工作进程不会因为网络流量而阻塞,等待“对手”——客户端——回应。走完自己的这一步,它立即去处理其他已等待的棋步,或者迎接新参与者。
为什么这比阻塞式多进程架构更快?
NGINX 的扩展能力很好,每个工作进程可支撑数十万条连接。每条新连接只增加一个文件描述符,并在工作进程中消耗少量额外内存,因此连接的额外开销很低。NGINX 进程可以固定在 CPU 上,上下文切换相对少见,通常发生在没有工作可做时。
在阻塞式“一连接一进程”方法中,每条连接都需要大量额外资源和开销,进程之间的上下文切换非常频繁。
想看更详细的解释,可阅读 NGINX, Inc. 联合创始人、企业发展副总裁 Andrew Alexeev 撰写的 NGINX 架构文章。
经过适当的系统调优,NGINX 每个工作进程能够处理数十万条并发 HTTP 连接,并从容吸收流量突增,也就是大量新棋局涌入。
更新配置与升级 NGINX
NGINX 的进程架构只使用少量工作进程,使配置更新乃至 NGINX 二进制程序的升级都很高效。

更新 NGINX 配置是一项简单、轻量、可靠的操作。通常只需执行 nginx -s reload,检查磁盘上的配置,并向主进程发送 SIGHUP 信号。
主进程收到 SIGHUP 后会做两件事:
- 重新加载配置,并派生一组新的工作进程。新进程立即使用新配置接收连接、处理流量。
- 通知旧工作进程优雅退出。旧进程停止接收新连接;当前每个 HTTP 请求完成后,干净地关闭连接,不保留空闲 keepalive。所有连接关闭后,工作进程退出。
重载可能短暂增加 CPU 和内存使用,但相对于活跃连接的资源负载,通常不明显。配置可以每秒重载多次,很多 NGINX 用户正是这样做的。极少数情况下,多代工作进程等待连接关闭会造成问题,但通常也能很快解决。
NGINX 的二进制升级过程实现了高可用的理想目标:可以在线升级软件,而不丢失连接、不停机、不打断服务。

二进制升级的方法类似于配置的优雅重载。一个新的 NGINX 主进程与原主进程并行运行,共享监听套接字。两个主进程都活跃,各自的工作进程处理流量,然后可以通知旧主进程及其工作进程优雅退出。
完整过程见控制 NGINX文档。
结论
NGINX 架构信息图展示了 NGINX 工作方式的高层概览。但这份简单解释背后,是十多年的创新与优化:让 NGINX 在各种硬件上提供尽可能好的性能,同时维持现代 Web 应用所要求的安全性和可靠性。
想进一步了解 NGINX 的优化,可以阅读以下资源:
- NGINX 性能调优
- 开源应用架构:NGINX
- NGINX 1.9.1 的套接字分片(使用
SO_REUSEPORT套接字选项)
来源与版权
原文作者:Owen Garrett,NGINX Community Blog,2015-06-10。依用户已声明的转载授权译载。架构图、Kiril Georgiev 配图与原图说明保留,原文关联的纽约时报链接保留。未另行推定第三方图片为公共领域。 阅读原文。











暂无评论内容