深入 NGINX: 我们如何设计性能和扩展

NGINX 能在 web 性能中取得领先地位,这是由于其软件设计所决定的。许多 web 服务器和应用程序服务器使用一个简单的基于线程或进程的架构,NGINX 立足于一个复杂的事件驱动的体系结构,使它能够在现代硬件上扩展到成千上万的并发连接。

下面这张深入 NGINX 的信息图从高层次的进程架构上深度挖掘说明了 NGINX 如何在单一进程里保持多个连接。这篇博客进一步详细地解释了这一切是如何工作的。

知识 – NGINX 进程模型

Master Process

为了更好的理解这个设计,你需要理解 NGINX 如何运行的。NGINX 有一个主进程(它执行特权操作,如读取配置和绑定端口)和一些工作进程与辅助进程。


  1. # service nginx restart
  2. * Restarting nginx
  3. # ps -ef --forest | grep nginx
  4. root 32475 1 0 13:36 ? 00:00:00 nginx: master process /usr/sbin/nginx \
  5. -c /etc/nginx/nginx.conf
  6. nginx 32476 32475 0 13:36 ? 00:00:00 \_ nginx: worker process
  7. nginx 32477 32475 0 13:36 ? 00:00:00 \_ nginx: worker process
  8. nginx 32479 32475 0 13:36 ? 00:00:00 \_ nginx: worker process
  9. nginx 32480 32475 0 13:36 ? 00:00:00 \_ nginx: worker process
  10. nginx 32481 32475 0 13:36 ? 00:00:00 \_ nginx: cache manager process
  11. nginx 32482 32475 0 13:36 ? 00:00:00 \_ nginx: cache loader process

在四核服务器,NGINX 主进程创建了4个工作进程和两个管理磁盘内容缓存的缓存辅助进程。

为什么架构很重要?

任何 Unix 应用程序的根本基础是线程或进程。(从 Linux 操作系统的角度来看,线程和进程大多是相同的,主要的区别是他们共享内存的程度。)一个线程或进程是一个自包含的指令集,操作系统可以在一个 CPU 核心上调度运行它们。大多数复杂的应用程序并行运行多个线程或进程有两个原因:

  • 它们可以同时使用更多的计算核心。
  • 线程或进程可以轻松实现并行操作。(例如,在同一时刻保持多连接)。

进程和线程消耗资源。他们每个都使用内存和其他系统资源,他们会在 CPU 核心中换入和换出(这个操作叫做上下文切换)。大多数现代服务器可以并行保持上百个小型的、活动的线程或进程,但是一旦内存耗尽或高 I/O 压力引起大量的上下文切换会导致性能严重下降。

网络应用程序设计的常用方法是为每个连接分配一个线程或进程。此体系结构简单、容易实现,但是当应用程序需要处理成千上万的并发连接时这种结构就不具备扩展性。

NGINX 如何工作?

NGINX 使用一种可预测的进程模式来分配可使用的硬件资源:

  • 主进程(master)执行特权操作,如读取配置和绑定端口,然后创建少量的子进程(如下的三种类型)。
  • 缓存加载器进程(cache loader)在加载磁盘缓存到内存中时开始运行,然后退出。适当的调度,所以其资源需求很低。
  • 缓存管理器进程(cache manager)定期裁剪磁盘缓存中的记录来保持他们在配置的大小之内。
  • 工作进程(worker)做所有的工作!他们保持网络连接、读写内容到磁盘,与上游服务器通信。

在大多数情况下 NGINX 的配置建议:每个 CPU 核心运行一个工作进程,这样最有效地利用硬件资源。你可以在配置中包含 worker_processes auto指令配置:

worker_processes auto;

当一个 NGINX 服务处于活动状态,只有工作进程在忙碌。每个工作进程以非阻塞方式保持多连接,以减少上下文交换。

每个工作进程是一个单一线程并且独立运行,它们会获取新连接并处理之。这些进程可以使用共享内存通信来共享缓存数据、会话持久性数据及其它共享资源。(在 NGINX 1.7.11 及其以后版本,还有一个可选的线程池,工作进程可以转让阻塞的操作给它。更多的细节,参见“NGINX 线程池可以爆增9倍性能!”。对于 NGINX Plus 用户,该功能计划在今年晚些时候加入到 R7 版本中。)

NGINX 工作进程内部

每个 NGINX 工作进程按照 NGINX 配置初始化,并由主进程提供一组监听端口。

NGINX 工作进程首先在监听套接字上等待事件(accept_mutex 和内核套接字分片)。事件被新进来的连接初始化。这些连接被分配到一个状态机 – HTTP 状态机是最常用的,但 NGINX 也实现了流式(原始 TCP )状态机和几种邮件协议(SMTP、IMAP和POP3)的状态机。

Internet Requests

状态机本质上是一组指令,告诉 NGINX 如何处理一个请求。大多数 web 服务器像 NGINX 一样使用类似的状态机来实现相同的功能 - 区别在于实现。

调度状态机

把状态机想象成国际象棋的规则。每个 HTTP 事务是一个象棋游戏。一方面棋盘是 web 服务器 —— 一位大师可以非常迅速地做出决定。另一方面是远程客户端 —— 在一个相对较慢的网络下 web 浏览器访问网站或应用程序。

不管怎样,这个游戏规则很复杂。例如,web 服务器可能需要与各方沟通(代理一个上游的应用程序)或与身份验证服务器对话。web 服务器的第三方模块甚至可以扩展游戏规则。

一个阻塞状态机

回忆我们之前的描述,一个进程或线程就像一套独立的指令集,操作系统可以在一个 CPU 核心上调度运行它。大多数 web 服务器和 web 应用使用每个连接一个进程或者每个连接一个线程的模式来玩这个“象棋游戏”。每个进程或线程都包含玩完“一个游戏”的指令。在服务器运行该进程的期间,其大部分的时间都是“阻塞的” —— 等待客户端完成它的下一步行动。

Blocking I/O

  1. web 服务器进程在监听套接字上监听新连接(客户端发起新“游戏”)
  2. 当它获得一个新游戏,就玩这个游戏,每走一步去等待客户端响应时就阻塞了。
  3. 游戏完成后,web 服务器进程可能会等待是否有客户机想要开始一个新游戏(这里指的是一个“保持的”连接)。如果这个连接关闭了(客户端断开或者发生超时),web 服务器进程会返回并监听一个新“游戏”。

要记住最重要的一点是每个活动的 HTTP 连接(每局棋)需要一个专用的进程或线程(象棋高手)。这个结构简单容并且易扩展第三方模块(“新规则”)。然而,还是有巨大的不平衡:尤其是轻量级 HTTP 连接其实就是一个文件描述符和小块内存,映射到一个单独的线程或进程,这是一个非常重量级的系统对象。这种方式易于编程,但太过浪费。

NGINX是一个真正的象棋大师

也许你听过车轮表演赛游戏,有一个象棋大师同时对战许多对手?

列夫·吉奥吉夫在保加利亚的索非亚同时对阵360人。他的最终成绩是284胜70平6负。

这就是 NGINX 工作进程如何“下棋”的。每个工作进程(记住 - 通常每个CPU核心上有一个工作进程)是一个可同时对战上百人(事实是,成百上千)的象棋大师。

Event-driven Architecture

  1. 工作进程在监听和连接套接字上等待事件。
  2. 事件发生在套接字上,并且由工作进程处理它们:
    • 在监听套接字的事件意味着一个客户端已经开始了一局新棋局。工作进程创建了一个新连接套接字。
    • 在连接套接字的事件意味着客户端已经下了一步棋。工作进程及时响应。

一个工作进程在网络流量上从不阻塞,等待它的“对手”(客户端)做出反应。当它下了一步,工作进程立即继续其他的游戏,在那里工作进程正在处理下一步,或者在门口欢迎一个新玩家。

为什么这个比阻塞式多进程架构更快?

NGINX 每个工作进程很好的扩展支撑了成百上千的连接。每个连接在工作进程中创建另外一个文件描述符和消耗一小部分额外内存。每个连接有很少的额外开销。NGINX 进程可以固定在某个 CPU 上。上下文交换非常罕见,一般只发生在没有工作要做时。

在阻塞方式,每个进程一个连接的方法中,每个连接需要大量额外的资源和开销,并且上下文切换(从一个进程切换到另一个)非常频繁。

更详细的解释,看看这篇关于 NGINX 架构的文章,它由NGINX公司开发副总裁及共同创始人 Andrew Alexeev 写的。

通过适当的系统优化,NGINX 的每个工作进程可以扩展来处理成千上万的并发 HTTP 连接,并能脸不红心不跳的承受峰值流量(大量涌入的新“游戏”)。

更新配置和升级 NGINX

NGINX 的进程体系架构使用少量的工作进程,有助于有效的更新配置文件甚至 NGINX 程序本身。

Updating Configuration

更新 NGINX 配置文件是非常简单、轻量、可靠的操作。典型的就是运行命令 nginx –s reload,所做的就是检查磁盘上的配置并发送 SIGHUP 信号给主进程。

当主进程接收到一个 SIGHUP 信号,它会做两件事:

  • 重载配置文件和分支出一组新的工作进程。这些新的工作进程立即开始接受连接和处理流量(使用新的配置设置)
  • 通知旧的工作进程优雅的退出。工作进程停止接受新的连接。当前的 http 请求一旦完成,工作进程就彻底关闭这个连接(那就是,没有残存的“保持”连接)。一旦所有连接关闭,这个工作进程就退出。

这个重载过程能引发一个 CPU 和内存使用的小峰值,但是跟活动连接加载的资源相比它一般不易察觉。每秒钟你可以多次重载配置(很多 NGINX 用户都这么做)。非常罕见的情况下,有很多世代的工作进程等待关闭连接时会发生问题,但即使是那样也很快被解决了。

NGINX 的程序升级过程中拿到了高可用性圣杯 —— 你可以随时更新这个软件,不会丢失连接,停机,或者中断服务。

New Binary

程序升级过程类似于平滑重载配置的方法。一个新的 NGINX 主进程与原主进程并行运行,然后他们共享监听套接字。两个进程都是活动的,并且各自的工作进程处理流量。然后你可以通知旧的主进程和它的工作进程优雅的退出。

整个过程的详细描述在 NGINX 管理

结论

深入 NGINX 信息图提供一个 NGINX 功能实现的高层面概览,但在这简单的解释的背后是超过十年的创新和优化,使得 NGINX 在广泛的硬件上提供尽可能最好的性能同时保持了现代 Web 应用程序所需要的安全性和可靠性。

原文发布时间为:2015-06-24


本文来自合作伙伴“Linux中国”

时间: 2024-11-10 01:14:29

深入 NGINX: 我们如何设计性能和扩展的相关文章

Consul实践之Consul结合nginx构建高可用可扩展的Web服务

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dgd2010.blog.51cto.com/1539422/1730439 前文<Consul实践之Consul是什么>讲述了consul是什么,这篇文档是一个Consul实际应用的一个例子,用Consul结合nginx构建高可用可扩展的Web服务.Consul还能做许多其他的事情,可以根据实际需要构思和使用. 方案概述 nginx提供的负载均衡服务同样支持高可用.可扩展的W

linux系统nginx php-fpm安装php memcache扩展

下面来看一篇关于linux系统nginx php-fpm安装php memcache扩展教程,当然有不少办法可以安装memcache的插件不过如果你使用了php-fpm 和nginx驱动php采用那些sudo apt-get install php5-memcache可能就不好用了. 说说如果你把php手动安装在特别目录的情况下如何配置memcache php调用吧. 上下文参考我写的php-fpm安装那篇博客吧.  代码如下 复制代码 cd /data1/server/php-cgi/bin

nginx的几个高级扩展应用

nginx.conf 配置解释 详解user www www; 定义 Nginx 运行的用户及组 worker_processes 8; #[ debug | info | notice | warn | error | crit ] error_log /data1/logs/nginx_error.log crit; pid /usr/local/webserver/nginx/nginx.pid; #Specifies the value for maximum file descript

Nginx 配置文件总结

# 定义Nginx运行用户 user root; # Nginx进程数,设置为auto代表nginx会自己匹配,一般为CPU核心数量 worker_processes auto; # 错误日志路径及级别 error_log logs/error.log notice; # pid文件存放位置 pid logs/nginx.pid; # Nginx最大文件打开数 worker_rlimit_nofile 40960; events { #参考事件模型,use [ kqueue | rtsig |

Nginx流媒体支持配置

Nginx是一个短小精悍,且性能超强的Web服务器,同时也可以用作反向代理服务器以及邮件服务器.除此之外Nginx也可以用于搭建一个简易的流媒体服务器.基于此,本文描述了在Nginx 1.8之上构建一个简易的流媒体服务器,同时通过反向代理的方式将其代理至流媒体服务器. 有关Nginx相关的基础知识 Linux 6下安装编译安装Nginx Nginx 概述及日常管理 Nginx基于IP,端口,域名配置虚拟主机 Linux 下配置nginx到php的连接 一.当前的运行环境及安装文件 1.当前的运行

Nginx 何时取代 Apache?

Nginx和Apache都是流行的开源Web服务器.Apache是世界使用排名第一的Web服务器软件,是Apache软件基金会的一个开源Web服务器,几乎所有的计算机平台都可以运行,由于其开放的API接口,使得Apache有超多的模块,基本想到的都可以找到:加之历史悠久,因此相关文档齐全,因此,长期雄踞Web服务器市场的巅峰. 而Nginx最初是俄罗斯程序员Igor Sysoev开发的轻量级开源Web服务器,同时也是一个反向代理服务器和电子邮件代理服务器,并在一个BSD-like协议下发行. A

Nginx 将增加动态模块,用户可修改服务器

Nginx 将增加一个动态模块(dynamic modules)功能和一个基于 SaaS 的监控工具 Amplify,使它的 Web 服务器更加灵活和更好管理.这个动态模块和 Amplify 技术都是在本周的 nginx.conf 大会公布的. 增加动态模块后,会更加方便模块开发者分享 Nginx 的 Web 服务器的扩展.Nginx 的产品总监Owen Garrett 说,创建模块到 Nginx 之前很有挑战性,因为模块被构造和发出后,Nginx 的服务器就不允许再修改了,而动态模块允许添加额

Nginx何时取代Apache?

Nginx和Apache都是流行的开源Web服务器.Apache是世界使用排名第一的Web服务器软件,是Apache软件基金会的一个开源Web服务器,几乎所有的计算机平台都可以运行,由于其开放的API接口,使得Apache有超多的模块,基本想到的都可以找到:加之历史悠久,因此相关文档齐全,因此,长期雄踞Web服务器市场的巅峰. 而Nginx最初是俄罗斯程序员Igor Sysoev开发的轻量级开源Web服务器,同时也是一个反向代理服务器和电子邮件代理服务器,并在一个BSD-like协议下发行. A

LEMP环境搭配配置教程(Ubuntu16.04+Nginx+MySQL+PHP)

前言 拿到一台新装的Linux服务器,该如何配置成一台可以解析动态网页脚本的Web服务器呢? 相信这是很多人都会有的问题.本文将一步一步带你从头开始搭建给予LEMP技术栈的Web服务器,并使其可以正常运行PHP.Nodejs等语言. 所谓的LEMP技术栈,顾名思义其实就是Linux, Nginx, MySQL, PHP的组合.当然,如果喜欢,你也可以不用Nginx,而去选择Apache,这就是所谓的LAMP技术栈了. 本文使用Linux版本为Ubuntu 16.04 64位版本. TL;DR.