ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Nginx应用与运维——Nginx概述

2026/10/1 22:01:20 拓冰建站 浏览量
Nginx应用与运维——Nginx概述 Nginx概述1、Nginx的不同版本1.1、开源版Nginx1.2、商业版Nginx Plus1.3、分支版本Tengine1.4、扩展版本OpenResty2、Nginx源码架构浅析2.1、多进程模型2.1.1、信号2.1.2、频道2.1.3、共享内存2.1.4、进程调度2.1.5、事件驱动2.2、工作流机制2.2.1、HTTP请求处理阶段2.2.2、TCP/UDP处理阶段2.3、模块化2.3.1、模块分类2.3.2、动态模块Nginx发音同“engine x”​是一个高性能的反向代理和Web服务器软件最初是由俄罗斯人Igor Sysoev开发的。Nginx的第一个版本发布于2004年其源代码基于双条款BSD许可证发布因其系统资源消耗低、运行稳定且具有高性能的并发处理能力等特性Nginx在互联网企业中得到广泛应用。Nginx是互联网上最受欢迎的开源Web服务器之一它不仅提供了用于开发和交付的一整套应用技术还是应用交付领域的开源领导者。Netcraft公司2019年7月的统计数据表明Nginx为全球最繁忙网站中的25.42%提供了服务或代理进一步扩大了其在主机域名领域的占有量新增5220万个站点总数达4.4亿个市场占有率已经超过Apache 4.89%。得益于近几年云计算和微服务的快速发展Nginx因在其中发挥了自身优势而得到广泛应用且有望在未来占有更多的市场份额。2019年3月著名硬件负载均衡厂商F5宣布收购Nginx,Nginx成为F5的一部分。F5表示将加强对开源和Nginx应用平台的投资致力于Nginx开源技术、开发人员和社区的发展更大的投资将为开放源码计划注入新的活力会主办更多的开放源码活动并产生更多的开放源码内容。1、Nginx的不同版本作为最受欢迎的Web服务器之一Nginx自2004年发布以来已经得到很多互联网企业的应用。官方目前有Nginx开源版和Nginx Plus商业版两个版本开源版是目前使用最多的版本商业版除了包含开源版本的全部功能外还提供了一些独有的企业级功能。Nginx在国内互联网企业中也得到了广泛应用企业在实际使用中会根据自身的需求进行相应的扩展和增强。目前国内流行的Nginx主要有两个开源版本分别是由淘宝网技术团队维护的Tengine项目和由章亦春发起的OpenResty项目。1.1、开源版NginxNginx开源版一直处于活跃开发状态由Nginx公司负责开发与维护。截至本书写作时Nginx开源版本已经更新到1.17.2版本。Nginx自推出以来一直专注于低资源消耗、高稳定、高性能的并发处理能力除了提供Web服务器的功能外还实现了访问代理、负载均衡、内容缓存、访问安全及带宽控制等功能。其基于模块化的代码架构及可与其他开发语言如Perl、JavaScript和Lua有效集成的可编程特性使其具有强大的扩展能力。部署和优化具有高效率、高性能并发请求处理能力的应用架构是应用架构师一直追求的目标在应用架构技术的迭代中各种分离式思想成为主流比如将访问入口和Web服务器分离、将Web服务器和动态脚本解析器分开、将Web功能不断拆分、微服务等。Nginx不仅提供了Web服务器的功能还极大满足了这一主流架构的需求并提供了如下应用特性。(1)访问路由现今大型网站的请求量早已不是单一Web服务器可以支撑的了。单一入口、访问请求被分配到不同的业务功能服务器集群是目前大型网站的通用应用架构。Nginx可以通过访问路径、URL关键字、客户端IP、灰度分流等多种手段实现访问路由分配。(2)反向代理就反向代理功能而言Nginx本身并不产生响应数据只是应用自身的异步非阻塞事件驱动架构高效、稳定地将请求反向代理给后端的目标应用服务器并把响应数据返回给客户端。其不仅可以代理HTTP协议还支持HTTPS、HTTP/2、FastCGI、uWSGI、SCGI、gRPC及TCP/UDP等目前大部分协议的反向代理。(3)负载均衡Nginx在反向代理的基础上集合自身的上游(upstream)模块支持多种负载均衡算法使后端服务器可以非常方便地进行横向扩展从而有效提升应用的处理能力使整体应用架构可轻松应对高并发的应用场景。(4)内容缓存动态处理与静态内容分离是应用架构优化的主要手段之一Nginx的内容缓存技术不仅可以实现预置静态文件的高速缓存还可以对应用响应的动态结果实现缓存为响应结果变化不大的应用提供更高速的响应能力。(5)可编程Nginx模块化的代码架构方式为其提供了高度可定制的特性但可以用C语言开发Nginx模块以满足自身使用需求的用户只是少数。Nginx在开发之初就具备了使用Perl脚本语言实现功能增强的能力。Nginx对JavaScript语言及第三方模块对Lua语言的支持使得其可编程能力更强。Nginx开源版本维护了两个版本分支分别为主线(mainline)分支和稳定(stable)分支。主线分支是一个活跃分支会添加一些最新的功能并进行错误修复由版本号中的第二位奇数标识截至本书写作时的最新版本为1.17.2。稳定分支会集成修复严重错误的代码但不会增加新的功能由版本号中的第二位偶数标识截至本书写作时的最新版本为1.16.1。想了解更多内容的用户可参阅官方网站http://www.nginx.org。1.2、商业版Nginx PlusNginx Plus是Nginx于2013年推出的商业版本在开源版本的基础上增加了使用户对Nginx的管理和监控更轻松的功能。其代码在单独的私有代码库中维护。它始终基于最新版本的Nginx开源版本主线分支并包含一些封闭源代码特性和功能。因此除了开源版本中提供的功能外Nginx Plus还具有独有的企业级功能包括实时活动监视数据、通过API配置上游服务器负载平衡和主动健康检查等。相对于开源版本Nginx Plus还提供了以下几个功能。(1)负载均衡基于cookies的会话保持功能。基于响应状态码和响应体的主动健康监测。支持DNS动态更新。(2)动态管理支持通过API清除内容缓存。可通过API动态管理上游的后端服务器列表。(3)安全控制基于API和OpenID连接协议单点登录(SSO)的JWT(JSON Web Token)认证支持。Nginx WAF动态模块。(4)状态监控超过90个状态指标的扩展状态监控。内置实时图形监控面板。集成可用于自定义监控工具的JSON和HTML输出功能支持。(5)Kubernetes Ingress Controller支持Kubernetes集群Pod的会话保持和主动健康监测。支持JWT身份认证。(6)流媒体支持自适性串流(Adaptive Bitrate Streaming, ABS)媒体技术HLS(Apple HTTP Live Streaming)和HDS(AdobeHTTP Dynamic Streaming)。支持对MP4媒体流进行带宽控制。商业版本的功能比开源版本更加完善为用户提供了更多的技术解决方案和支持。想了解更多内容的读者可参阅官方网站http://www.nginx.com。1.3、分支版本TengineTengine是由淘宝网技术团队发起的Nginx二次开发项目是在开源版Nginx及诸多第三方模块的基础上针对淘宝网的高并发需求进行的二次开发。其中添加了很多针对互联网网站中使用Nginx应对高并发负载、安全及维护等的功能和特性。据Tengine官网介绍Tengine不仅在淘宝网上使用搜狗、天猫、大众点评、携程、开源中国等也在使用其性能和稳定性得到了有效检验。Tengine从2011年12月开始成为开源项目Tengine团队的核心成员来自淘宝、搜狗等互联网企业。截至本书写作时Tengine的最新版本是2.3.2在继承Nginx 1.17.3版本的所有功能的同时也保持了自有的对Nginx的优化和增强其增强特性如下。继承Nginx 1.17.3版本的所有特性兼容Nginx的配置。支持HTTP的CONNECT方法可用于正向代理场景。支持异步OpenSSL可使用硬件如QAT进行HTTPS的加速与卸载。增强相关运维、监控能力如异步打印日志及回滚、本地DNS缓存、内存监控等。Stream模块支持server_name指令。支持输入过滤器机制。该机制的使用使得Web应用防火墙的编写更为方便。支持设置Proxy、Memcached、FastCGI、SCGI、uWSGI在后端失败时的重试次数。支持动态脚本语言Lua其扩展功能非常高效简单。支持按指定关键字域名、URL等收集Tengine运行状态。更强大的防攻击访问速度限制模块。Tengine是基于Nginx开发的轻量级开源Web服务器作为阿里巴巴七层流量入口的核心系统支撑着阿里巴巴“双11”等大促活动的平稳度过并提供了智能的流量转发策略、HTTPS加速、安全防攻击、链路追踪等众多高级特性同时秉着软硬件结合的性能优化思路在高性能、高并发方面取得了重大突破。目前Tengine正通过打通Ingress Controller和Kubernetes使Tengine具备动态感知某个服务整个生命周期的能力。未来Tengine将定期开源内部通用组件功能模块并同步Nginx官方的最新代码丰富开发者们的开源Web服务器选项。想了解更多内容的读者请参阅官方网站http://tengine.taobao.org/。1.4、扩展版本OpenRestyOpenResty是基于Nginx开源版本的扩展版本它利用Nginx的模块特性使Nginx支持Lua语言的脚本编程鉴于Lua本身嵌入应用程序中增强应用程序扩展和定制功能的设计初衷开源版本Nginx的可编程性得到大大增强。据OpenResty官网介绍2017年全球互联网中至少有23万台主机正在使用Nginx的OpenResty版本作为Web服务器或网关应用。OpenResty®是一个基于Nginx与Lua的高性能Web平台其内部集成了大量精良的Lua库、第三方模块以及大多数依赖项以便搭建能够处理超高并发、扩展性极高的动态Web应用、Web服务和动态网关。OpenResty®通过汇聚各种设计精良的Nginx模块主要由OpenResty团队自主开发​将Nginx变成一个强大的通用Web应用平台。这样Web开发人员和系统工程师就可以使用Lua脚本语言调动Nginx支持的各种C模块及Lua模块快速构造出足以胜任一万乃至百万以上单机并发连接的高性能Web应用系统。OpenResty®的目标是让Web服务直接运行在Nginx服务内部充分利用Nginx的非阻塞I/O模型不仅对HTTP客户端请求还对远程后端如MySQL、PostgreSQL、Memcached及Redis等都进行一致的高性能响应。OpenResty构架在Nginx和LuaJIT的基础之上利用Nginx的模块特性集成了大量Lua支持库用户可以很方便地使用Lua编程语言对Nginx的功能进行扩展和增强。OpenResty通过基于Nginx优化的ngx.location.capture_multi功能可以非阻塞地并行转发多个子请求给后端服务器当后端服务器返回数据时进行相应的归类和排序处理进而有效提升客户端的请求响应速度。在OpenResty代码架构中其代码以ngx_lua模块的形式嵌入Nginx代码中从而使用户编写的Lua代码与Nginx进程协同工作。OpenResty为每个Nginx工作进程(Worker Process)创建了一个Lua虚拟机(LuaVM)如图所示并将Nginx I/O原语封装注入Lua虚拟机中供Lua代码访问每个外部请求都由Lua虚拟机产生一个Lua协程(coroutine)进行处理协程之间彼此数据隔离并共享对应的Lua虚拟机。当Lua代码调用异步接口时会挂起当前协程以不阻塞Nginx工作进程等异步接口处理完成时再还原当前协程继续运行。OpenResty项目开始于2007年10月最早是为雅虎中国搜索部门开发的项目后由章亦春进行开发和维护并得到了国内外诸多企业的应用目前主要由OpenResty软件基金会和OpenResty Inc.公司提供支持。2、Nginx源码架构浅析Nginx低资源消耗、高稳定、高性能的并发处理能力来源于其优秀的代码架构。它采用了多进程模型使自身具有低资源消耗的特性。以事件驱动的异步非阻塞多进程请求处理模型使Nginx的工作进程通过异步非阻塞的事件处理机制实现了高性能的并发处理能力让每个连接的请求均可在Nginx进程中以工作流的方式得到快速处理。Nginx代码架构充分利用操作系统的各种机制发挥了软硬件的最大性能使它在普通硬件上也可以处理数十万个并发连接。Nginx支持在多种操作系统下部署运行为发挥Nginx的最大性能需要对不同的平台进行细微的调整为方便了解Nginx架构的特点本书仅以Linux系统平台为例进行介绍。2.1、多进程模型进程是操作系统资源分配的最小单位由于CPU数量有限多个进程间通过被分配的时间片来获得CPU的使用权系统在进行内核管理和进程调度时要执行保存当前进程上下文、更新控制信息、选择另一就绪进程、恢复就绪进程上下文等一系列操作而频繁切换进程会造成资源消耗。Nginx采用的是固定数量的多进程模型见下图​由一个主进程(Master Process)和数量与主机CPU核数相同的工作进程协同处理各种事件。主管理进程负责工作进程的配置加载、启停等操作工作进程负责处理具体请求。进程间的资源都是独立的每个工作进程处理多个连接每个连接由一个工作进程全权处理不需要进行进程切换也就不会产生由进程切换引起的资源消耗问题。默认配置下工作进程的数量与主机CPU核数相同充分利用CPU和进程的亲缘性(affinity)将工作进程与CPU绑定从而最大限度地发挥多核CPU的处理能力。Nginx主进程负责监听外部控制信号通过频道机制将相关信号操作传递给工作进程多个工作进程间通过共享内存来共享数据和信息。2.1.1、信号信号(signal)又称软中断信号可通过调用系统命令kill来发送信号实现进程通信。在Nginx系统中主进程负责监听外部信号实现对进程的热加载、平滑重启及安全关闭等操作的响应。Nginx支持的信号如表所示。(1)在Linux系统下可以通过kill命令向Nginx进程发送信号指令代码如下kill-HUPcat nginx.pid(2)在Linux系统下也可以通过nginx -s命令行参数实现信号指令的发送代码如下nginx-sreload2.1.2、频道频道(channel)是Nginx主进程向工作进程传递信号操作的通信方式用于将控制工作进程的信号操作传递给工作进程。通信频道的原理是应用socketpair方法使用本机的socket方式实现进程间的通信。主进程发送频道消息工作进程接收频道消息并执行相应操作如工作进程的创建与停止等。创建工作进程时会将接收频道消息的套接字注册到对应的事件引擎如epoll中当事件引擎监听到主进程发送的频道消息时就会触发回调函数通知工作进程执行响应操作。2.1.3、共享内存共享内存是Linux操作系统下进程间的一种简单、高效的通信方式其允许多个进程访问同一个内存地址一个进程改变了内存中的内容后其他进程都可以使用变更后的内容。Nginx的多个进程间就是通过共享内存的方式共享数据的主进程启动时创建共享内存工作进程创建fork方式完成后所有的进程都开始使用共享内存。用户可以在配置文件中配置共享内存名称和大小定义不同的共享内存块供Nginx不同的功能使用Nginx解析完配置文件后会将定义的共享内存通过slab机制进行内部统一划分和管理。2.1.4、进程调度当工作进程被创建时每个工作进程都继承了主进程的监听套接字(socket)所以所有工作进程的事件监听列表中会共享相同的监听套接字。但是多个工作进程间同一时间内只能由一个工作进程接收网络连接为使多个工作进程间能够协调工作Nginx的工作进程有如下几种调度方式。(1)无调度模式所有工作进程都会在连接事件被触发时争相与客户端建立连接建立连接成功则开始处理客户端请求。无调度模式下所有进程都会争抢资源但最终只有一个进程可以与客户端建立连接对于系统而言这将在瞬间产生大量的资源消耗这就是所谓的惊群现象。(2)互斥锁模式(accept_mutex)互斥锁是一种声明机制每个工作进程都会周期性地争抢互斥锁一旦某个工作进程抢到互斥锁就表示其拥有接收HTTP建立连接事件的处理权并将当前进程的socket监听注入事件引擎如epoll中接收外部的连接事件。其他工作进程只能继续处理已经建立连接的读写事件并周期性地轮询查看互斥锁的状态只有互斥锁被释放后工作进程才可以抢占互斥锁获取HTTP建立连接事件的处理权。当工作进程最大连接数的1/8与该进程可用连接(free_connection)的差大于或等于1时则放弃本轮争抢互斥锁的机会不再接收新的连接请求只处理已建立连接的读写事件。互斥锁模式有效地避免了惊群现象对于大量HTTP的短连接该机制有效避免了因工作进程争抢事件处理权而产生的资源消耗。但对于大量启用长连接方式的HTTP连接互斥锁模式会将压力集中在少数工作进程上进而因工作进程负载不均而导致QPS下降。(3)套接字分片(Socket Sharding)套接字分片是由内核提供的一种分配机制该机制允许每个工作进程都有一组相同的监听套接字。当有外部连接请求时由内核决定哪个工作进程的套接字监听可以接收连接。这有效避免了惊群现象的发生相比互斥锁机制提高了多核系统的性能。该功能需要在配置listen指令时启用reuseport参数。Nginx 1.11.3以后的版本中互斥锁模式默认是关闭的由于Nginx的工作进程数量有限且Nginx通常会在高并发场景下应用很少有空闲的工作进程所以惊群现象的影响不大。无调度模式因少了争抢互斥锁的处理在高并发场景下可提高系统的响应能力。套接字分片模式则因为由Linux内核提供进程的调度机制所以性能最好。2.1.5、事件驱动事件驱动程序设计(Event-Driven Programming)是一种程序设计模型这种模型的程序流程是由外部操作或消息交互事件触发的。其代码架构通常是预先设计一个事件循环方法再由这个事件循环方法不断地检查当前要处理的信息并根据相应的信息触发事件函数进行事件处理。通常未被处理的事件会放在事件队列中等待处理而被事件函数处理的事件也会形成一个事件串因此事件驱动模型的重点就在于事件处理的弹性和异步化。为了确保操作系统运行的稳定性Linux系统将用于寻址操作的虚拟存储器分为内核空间和用户空间所有硬件设备的操作都是在内核空间中实现的。当应用程序监听的网络接口接收到网络数据时内核会先把数据保存在内核空间的缓冲区中然后再由应用程序复制到用户空间进行处理。Linux操作系统下所有的设备都被看作文件来操作所有的文件都通过文件描述符(File Descriptor, FD)集合进行映射管理。套接字是应用程序与TCP/IP协议通信的中间抽象层也是一种特殊的文件应用程序以文件描述符的方式对其进行读/写(I/O)、打开或关闭操作。每次对socket进行读操作都需要等待数据准备数据被读取到内核缓冲区​然后再将数据从内核缓冲区复制到用户空间。为了提高网络I/O操作的性能操作系统设计了多种I/O网络模型。在Linux系统下网络并发应用处理最常用的就是I/O多路复用模型该模型是一种一个进程可以监视多个文件描述符的机制一旦某个文件描述符就绪数据准备就绪​进程就可以进行相应的读写操作。epoll模型是Linux系统下I/O多路复用模型里最高效的I/O事件处理模型其最大并发连接数仅受内核的最大打开文件数限制在1GB内存下可以监听10万个端口。epoll模型监听的所有连接中只有数据就绪的文件描述符才会调用应用进程、触发响应事件从而提升数据处理效率。epoll模型利用mmap映射内存加速与内核空间的消息传递从而减少复制消耗。作为Web服务器Nginx的基本功能是处理网络事件快速从网络接口读写数据。Nginx结合操作系统的特点基于I/O多路复用模型的事件驱动程序设计采用了异步非阻塞的事件循环方法响应处理套接字上的accept事件使其在调用accept时不会长时间占用进程的CPU时间片从而能够及时处理其他工作。通过事件驱动的异步非阻塞机制见下图​使大量任务可以在工作进程中得到高效处理以应对高并发的连接和请求。2.2、工作流机制Nginx在处理客户端请求时每个连接仅由一个进程进行处理每个请求仅运行在一个工作流中工作流被划分为多个阶段见下图​请求在不同阶段由功能模块进行数据处理处理结果异常或结束则将结果返回客户端否则将进入下一阶段。工作进程维护工作流的执行并通过工作流的状态推动工作流完成请求操作的闭环。HTTP消息头包括请求头和响应头。2.2.1、HTTP请求处理阶段HTTP请求的处理过程可分为11个阶段HTTP请求处理阶段如下表所示。HTTP请求处理阶段可以让每个模块仅在该阶段独立完成该阶段可实现的功能而整个HTTP请求则是由多个功能模块共同处理完成的。2.2.2、TCP/UDP处理阶段TCP/UDP会话一共会经历7个处理阶段每个TCP/UDP会话会自上而下地按照7个阶段进行流转处理每个处理阶段的说明如下表所示。Nginx功能模块就是根据不同的功能目的按照模块开发的加载约定嵌入不同的处理阶段的。2.3、模块化Nginx一直秉持模块化的理念其模块化的架构中除了少量的主流程代码都是模块。模块化的设计为Nginx提供了高度的可配置、可扩展、可定制特性。模块代码包括核心模块和功能模块两个部分核心模块负责维护进程的运行、内存及事件的管理功能模块则负责具体功能应用的实现包括路由分配、内容过滤、网络及磁盘数据读写、代理转发、负载均衡等操作。Nginx的高度抽象接口使用户很容易根据开发规范进行模块开发有很多非常实用的第三方模块被广泛使用。2.3.1、模块分类核心模块(core)。该模块提供了Nginx服务运行的基本功能如Nginx的进程管理、CPU亲缘性、内存管理、配置文件解析、日志等功能。事件模块(event)。该模块负责进行连接处理提供对不同操作系统的I/O网络模型支持和自动根据系统平台选择最有效I/O网络模型的方法。HTTP模块(http)。该模块提供HTTP处理的核心功能和部分功能模块HTTP核心功能维护了HTTP多个阶段的工作流并实现了对各种HTTP功能模块的管理和调用。Mail模块(mail)。该模块实现邮件代理功能代理IMAP、POP3、SMTP协议。Stream模块(stream)。该模块提供TCP/UDP会话的代理和负载相关功能。第三方模块。第三方模块即非Nginx官方开发的功能模块据统计在开源社区发布的第三方模块已经达到100多个其中lua-resty、nginx-module-vts等模块的使用度非常高。2.3.2、动态模块Nginx早期版本在进行模块编译时通过编译配置(configure)选项–with_module和–without-module决定要编译哪些模块被选择的模块代码与Nginx核心代码被编译到同一个Nginx二进制文件中Nginx文件每次启动时都会加载所有的模块。这是一种静态加载模块的方式。随着第三方模块的增多和Nginx Plus的推出模块在不重新编译Nginx的情况下被动态加载成为迫切的需求。Nginx从1.9.11版本开始支持动态加载模块的功能该功能使Nginx可以在运行时有选择地加载Nginx官方或第三方模块。为使动态模块更易于使用Nginx官方还提供了pkg-oss工具该工具可为任何动态模块创建可安装的动态模块包。在Nginx开源版本的代码中编译配置选项中含有“dynamic”选项表示支持动态模块加载。例如模块http_xslt_module的动态模块编译配置选项示例如下。./configure --with-http_xslt_moduledynamic编译后模块文件以so文件的形式独立存储于Nginx的modules文件夹中。动态模块编译如图所示。在不同编译配置选项下Nginx在编译时会因为某些结构字段未被使用而不会将其编译到代码中因此就会出现不同编译配置选项的动态模块无法加载的问题。为解决这个问题Nginx在编译配置选项中提供了“–with-compat”选项在进行Nginx及动态模块编译配置时如果使用了该选项在相同版本的Nginx代码下动态模块即使与Nginx执行文件的其他编译配置选项不同也可以被Nginx执行文件加载。启用兼容参数编译的示例如下./configure --with-compat --with-http_xslt_moduledynamic可以在配置文件中使用load_module指令加载动态模块示例如下load_modulemodules/ngx_http_xslt_filter_module.so;