NGINX有一个master进程(它执行特权操作,如读取配置和绑定到端口)和许多worker and helper进程。
# 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 内核上运行。大多数复杂的应用程序并行运行多个线程或进程,原因有二:
进程和线程的运行会消耗资源。它们各自使用内存和其他操作系统资源,并且需要打开和切换内核(上下文切换)。大多数现代服务器可以同时处理数百个小型活动线程或进程,但是一旦内存耗尽或高 I/O 负载导致大量的上下文切换,性能就会严重下降。
设计网络应用程序的常用方法是为每个连接分配一个线程或进程。此体系结构简单且易于实现,但是当应用程序需要处理数千个同时连接时,它不易扩展。
NGINX使用可预测的进程模型,该模型根据可用的硬件资源进行调整:
在大多数情况下推荐的NGINX配置 - 每个CPU内核运行一个工作进程 - 可以最有效地利用硬件资源。您可以通过在指令上设置参数来配置它:autoworker_processes
worker_processes auto;
当NGINX服务器处于活动状态时,只有工作进程处于繁忙状态。每个工作进程都以非阻塞方式处理多个连接,从而减少了上下文切换的数量。
每个工作进程都是单线程的,并且独立运行。这些进程使用共享内存进行通信,以存储共享缓存数据、会话持久性数据和其他共享资源。
每个 NGINX 工作进程都使用 NGINX的配置进行初始化,并由主进程提供一组侦听套接字。
NGINX 工作进程首先等待侦听套接字(accept_mutex和内核套接字分片)上的事件。事件(Event)一旦有新的传入连接活动就会启动。这些连接被分配给状态机 (state machine)——HTTP 状态机是最常用的,但 NGINX 也为stream流(原始 TCP)和许多邮件协议(SMTP、IMAP 和 POP3)使用了状态机。
状态机本质上是一组指令,告诉 NGINX 如何处理请求。大多数执行与 NGINX 相同功能的 Web 服务器都使用类似的状态机——区别在于实现方式的不同。
把状态机想象成国际象棋的规则。每个 HTTP 事务都是一盘棋。棋盘的一侧是Web服务器——一个可以很快做出服务响应。另一方面是远程客户端——通过相对较慢的网络访问站点或应用程序的 Web 浏览器。
但是,游戏规则可能非常复杂。例如,Web 服务器可能需要与其他方通信(反向代理到其他上游应用)或与身份验证服务器通信。Web 服务器中的第三方模块可以扩展游戏规则。
回想一下我们将进程或线程描述为操作系统可以安排在 CPU 内核上运行的独立指令集。大多数 Web 服务器和应用程序使用每个连接的进程或线程模型进行工作。在服务器运行进程期间,它大部分时间都处于“阻塞”状态——因为需要等待客户端完成下一步。
要记住的重要一点是,每个活动的 HTTP 连接都需要一个专用的进程或线程。此架构简单且易于使用第三方模块进行扩展。
NGINX 工作进程的不同之处是每个worker进程(通常每个 CPU 内核对应一个worker进程)可以同时连接数十万个连接。
Worker进程会同时响应多个客户端的请求,不会因为没有收到其中一个客户端的响应,而让自己处于阻断状态。
NGINX 可以很好地扩展以支持每个工作进程数十万个连接。每个新连接都会创建新的文件描述符,并在工作进程中消耗少量内存。每个连接几乎没有额外的开销。NGINX 进程数量与CPU的内核个数相关联,上下文切换相对不频繁。
在阻塞、每个进程连接的工作环节中,每个连接都需要消耗大量的额外资源和开销,并且上下文切换(从一个进程切换到另一个进程)非常频繁。
通过适当的系统调优,NGINX 可以扩展为每个工作进程处理数十万个并发 HTTP 连接,并且可以在不漏掉任何一个请求的情况下继续响应新的请求。
NGINX 的进程架构,具有少量工作进程,可以非常有效地更新配置,或是升级软件本身。
更新 NGINX 配置是非常简单,运行nginx -s reload命令即可,该命令会检查NGINX的配置并向主进程发送 SIGHUP 信号。
当主进程收到 SIGHUP 时,它会做两件事:
新配置文件的加载过程可能会导致 CPU 和内存使用量出现小幅峰值,但与来自活动连接的资源负载相比,通常难以察觉。而且对NGINX进行软件升级 ,也不会出现任何掉线、停机或服务中断。
软件升级过程类似于优雅地重新加载配置。一个新的 NGINX 主进程与原来的主进程并行运行,它们共享监听套接字。两个进程都处于活动状态,它们各自的工作进程处理流量。最后旧的master 及其worker进程以优雅的方式退出。
翻译来源:Inside NGINX: How We Designed for Performance & Scale
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。