本文主要是介绍weixueyuan-nginx,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
https://www.weixueyuan.net/nginx/
Nginx是什么
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) 开源版 Nginx
Nginx 开源版一直处于活跃开发状态,由 Nginx 公司负责开发与维护。截至本教程写作时,Nginx 开源版本已经更新到 1.17.2 版本。Nginx 自推出以来,一直专注于低资源消耗、高稳定、高性能的并发处理能力,除了提供 Web 服务器的功能外,还实现了访问代理、负载均衡、内容缓存、访问安全及带宽控制等功能。其基于模块化的代码架构及可与其他开发语言(如 Perl、JavaScript 和 Lua)有效集成的可编程特性,使其具有强大的扩展能力。
部署和优化具有高效率、高性能并发请求处理能力的应用架构是应用架构师一直追求的目标,在应用架构技术的迭代中,各种分离式思想成为主流,比如将访问入口和 Web 服务器分离、将 Web 服务器和动态脚本解析器分开、将 Web 功能不断拆分、微服务等。
Nginx 不仅提供了 Web 服务器的功能,还极大满足了这一主流架构的需求并提供了如下应用特性。
① 访问路由
现今大型网站的请求量早已不是单一 Web 服务器可以支撑的了。单一入口、访问请求被分配到不同的业务功能服务器集群,是目前大型网站的通用应用架构。Nginx 可以通过访问路径、URL 关键字、客户端 IP、灰度分流等多种手段实现访问路由分配。
② 反向代理
就反向代理功能而言,Nginx 本身并不产生响应数据,只是应用自身的异步非阻塞事件驱动架构,高效、稳定地将请求反向代理给后端的目标应用服务器,并把响应数据返回给客户端。其不仅可以代理 HTTP 协议,还支持 HTTPS、HTTP/2、FastCGI、uWSGI、SCGI、gRPC 及 TCP/UDP 等目前大部分协议的反向代理。
③ 负载均衡
Nginx 在反向代理的基础上集合自身的上游(upstream)模块支持多种负载均衡算法,使后端服务器可以非常方便地进行横向扩展,从而有效提升应用的处理能力,使整体应用架构可轻松应对高并发的应用场景。
④ 内容缓存
动态处理与静态内容分离是应用架构优化的主要手段之一,Nginx 的内容缓存技术不仅可以实现预置静态文件的高速缓存,还可以对应用响应的动态结果实现缓存,为响应结果变化不大的应用提供更高速的响应能力。
⑤ 可编程
Nginx 模块化的代码架构方式为其提供了高度可定制的特性,但可以用C语言开发 Nginx 模块以满足自身使用需求的用户只是少数。Nginx 在开发之初就具备了使用 Perl 脚本语言实现功能增强的能力。Nginx 对 JavaScript 语言及第三方模块对 Lua 语言的支持,使得其可编程能力更强。
Nginx 开源版本维护了两个版本分支,分别为主线(mainline)分支和稳定(stable)分支。主线分支是一个活跃分支,会添加一些最新的功能并进行错误修复,由版本号中的第二位奇数标识,截至本教程写作时的最新版本为 1.17.2。稳定分支会集成修复严重错误的代码,但不会增加新的功能,由版本号中的第二位偶数标识,截至本教程写作时的最新版本为 1.16.1。想了解更多内容的用户可参阅 Nginx 官方网站。
2) 商业版 Nginx Plus
Nginx Plus 是 Nginx 于 2013 年推出的商业版本,在开源版本的基础上增加了使用户对 Nginx 的管理和监控更轻松的功能。其代码在单独的私有代码库中维护。它始终基于最新版本的 Nginx 开源版本主线分支,并包含一些封闭源代码特性和功能。因此,除了开源版本中提供的功能外,Nginx Plus 还具有独有的企业级功能,包括实时活动监视数据、通过 API 配置上游服务器负载平衡和主动健康检查等。
相对于开源版本,Nginx Plus 还提供了以下几个功能。
① 负载均衡
- 基于 cookies 的会话保持功能。
- 基于响应状态码和响应体的主动健康监测。
- 支持 DNS 动态更新。
② 动态管理
- 支持通过 API 清除内容缓存。
- 可通过 API 动态管理上游的后端服务器列表。
③ 安全控制
- 基于 API 和 OpenID 连接协议单点登录(SSO)的 JWT(JSON Web Token)认证支持。
- Nginx WAF 动态模块。
④ 状态监控
- 超过 90 个状态指标的扩展状态监控。
- 内置实时图形监控面板。
- 集成可用于自定义监控工具的 JSON 和 HTML 输出功能支持。
⑤ Kubernetes Ingress Controller
- 支持 Kubernetes 集群 Pod 的会话保持和主动健康监测。
- 支持 JWT 身份认证。
⑥ 流媒体
- 支持自适性串流(Adaptive Bitrate Streaming,ABS)媒体技术 HLS(Apple HTTP Live Streaming)和 HDS(Adobe HTTP Dynamic Streaming)。
- 支持对 MP4 媒体流进行带宽控制。
3) 分支版本 Tengine
Tengine 是由淘宝网技术团队发起的 Nginx 二次开发项目,是在开源版 Nginx 及诸多第三方模块的基础上,针对淘宝网的高并发需求进行的二次开发。其中添加了很多针对互联网网站中使用 Nginx 应对高并发负载、安全及维护等的功能和特性。
据 Tengine 官网介绍,Tengine 不仅在淘宝网上使用,搜狗、天猫、大众点评、携程、开源中国等也在使用,其性能和稳定性得到了有效检验。Tengine 从 2011 年 12 月开始成为开源项目,Tengine 团队的核心成员来自淘宝、搜狗等互联网企业。
Tengine 在继承 Nginx 的所有功能的同时,也保持了自有的对 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服务器选项。
4) 扩展版本 OpenResty
OpenResty 是基于 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 虚拟机。
![OpenResty Lua虚拟机](/upload/202204/26/202204260712522833.gif)
图:OpenResty Lua虚拟机
当 Lua 代码调用异步接口时,会挂起当前协程以不阻塞 Nginx 工作进程,等异步接口处理完成时再还原当前协程继续运行。
OpenResty 项目开始于 2007 年 10 月,最早是为雅虎中国搜索部门开发的项目,后由章亦春进行开发和维护,并得到了国内外诸多企业的应用,目前主要由 OpenResty 软件基金会和 OpenResty Inc. 公司提供支持。
Nginx源码架构分析
Nginx 低资源消耗、高稳定、高性能的并发处理能力,来源于其优秀的代码架构。它采用了多进程模型,使自身具有低资源消耗的特性。以事件驱动的异步非阻塞多进程请求处理模型,使 Nginx 的工作进程通过异步非阻塞的事件处理机制,实现了高性能的并发处理能力,让每个连接的请求均可在 Nginx 进程中以工作流的方式得到快速处理。
Nginx 代码架构充分利用操作系统的各种机制,发挥了软硬件的最大性能,使它在普通硬件上也可以处理数十万个并发连接。而且 Nginx 支持在多种操作系统下部署运行,为发挥 Nginx 的最大性能,需要对不同的平台进行细微的调整,为方便了解 Nginx 架构的特点,本教程仅以 Linux 系统平台为例进行介绍。
1、多进程模型
进程是操作系统资源分配的最小单位,由于 CPU 数量有限,多个进程间通过被分配的时间片来获得 CPU 的使用权,系统在进行内核管理和进程调度时,要执行保存当前进程上下文、更新控制信息、选择另一就绪进程、恢复就绪进程上下文等一系列操作,而频繁切换进程会造成资源消耗。
Nginx 采用的是固定数量的多进程模型(见下图),由一个主进程(Master Process)和数量与主机 CPU 核数相同的工作进程协同处理各种事件。主管理进程负责工作进程的配置加载、启停等操作,工作进程负责处理具体请求。
![多进程模型](/upload/202204/26/202204260712523839.gif)
图:多进程模型
进程间的资源都是独立的,每个工作进程处理多个连接,每个连接由一个工作进程全权处理,不需要进行进程切换,也就不会产生由进程切换引起的资源消耗问题。默认配置下,工作进程的数量与主机 CPU 核数相同,充分利用 CPU 和进程的亲缘性(affinity)将工作进程与 CPU 绑定,从而最大限度地发挥多核 CPU 的处理能力。
Nginx 主进程负责监听外部控制信号,通过频道机制将相关信号操作传递给工作进程,多个工作进程间通过共享内存来共享数据和信息。
1) 信号
信号(signal)又称软中断信号,可通过调用系统命令
kill
来发送信号实现进程通信。在 Nginx 系统中,主进程负责监听外部信号,实现对进程的热加载、平滑重启及安全关闭等操作的响应。
Nginx 支持的信号如下表所示。
信号 | 命令行参数 | 功能 |
TERM 或 INT |
stop |
快速关闭 Nginx 服务 |
QUIT |
quit |
安全关闭 Nginx 服务 |
HUP |
reload |
热加载配置文件 |
WINCH |
|
安全关闭工作进程 |
USR1 |
reopen |
重新创建日志文件 |
USR2 |
|
平滑更新 Nginx 执行文件 |
在 Linux 系统下可以通过 kill 命令向 Nginx 进程发送信号指令,代码如下:
kill -HUP 'cat nginx.pid'
在 Linux 系统下也可以通过 nginx -s 命令行参数实现信号指令的发送,代码如下:
nginx -s reload
2) 频道
频道(channel)是 Nginx 主进程向工作进程传递信号操作的通信方式,用于将控制工作进程的信号操作传递给工作进程。通信频道的原理是应用 socketpair 方法使用本机的 socket 方式实现进程间的通信。主进程发送频道消息,工作进程接收频道消息并执行相应操作,如工作进程的创建与停止等。
创建工作进程时会将接收频道消息的套接字注册到对应的事件引擎(如 epoll)中,当事件引擎监听到主进程发送的频道消息时,就会触发回调函数通知工作进程执行响应操作。
3) 共享内存
共享内存是 Linux 操作系统下进程间的一种简单、高效的通信方式,其允许多个进程访问同一个内存地址,一个进程改变了内存中的内容后,其他进程都可以使用变更后的内容。Nginx 的多个进程间就是通过共享内存的方式共享数据的,主进程启动时创建共享内存,工作进程创建(fork 方式)完成后,所有的进程都开始使用共享内存。
用户可以在配置文件中配置共享内存名称和大小,定义不同的共享内存块供 Nginx 不同的功能使用,Nginx 解析完配置文件后,会将定义的共享内存通过 slab 机制进行内部统一划分和管理。
4) 进程调度
当工作进程被创建时,每个工作进程都继承了主进程的监听套接字(socket),所以所有工作进程的事件监听列表中会共享相同的监听套接字。但是多个工作进程间同一时间内只能由一个工作进程接收网络连接,为使多个工作进程间能够协调工作,Nginx 的工作进程有如下几种调度方式。
① 无调度模式
所有工作进程都会在连接事件被触发时争相与客户端建立连接,建立连接成功则开始处理客户端请求。无调度模式下所有进程都会争抢资源,但最终只有一个进程可以与客户端建立连接,对于系统而言这将在瞬间产生大量的资源消耗,这就是所谓的惊群现象。
② 互斥锁模式(accept_mutex)
互斥锁是一种声明机制,每个工作进程都会周期性地争抢互斥锁,一旦某个工作进程抢到互斥锁,就表示其拥有接收 HTTP 建立连接事件的处理权,并将当前进程的 socket 监听注入事件引擎(如 epoll)中,接收外部的连接事件。
其他工作进程只能继续处理已经建立连接的读写事件,并周期性地轮询查看互斥锁的状态,只有互斥锁被释放后工作进程才可以抢占互斥锁,获取 HTTP 建立连接事件的处理权。当工作进程最大连接数的 1/8 与该进程可用连接(free_connection)的差大于或等于 1 时,则放弃本轮争抢互斥锁的机会,不再接收新的连接请求,只处理已建立连接的读写事件。
互斥锁模式有效地避免了惊群现象,对于大量 HTTP 的短连接,该机制有效避免了因工作进程争抢事件处理权而产生的资源消耗。但对于大量启用长连接方式的 HTTP 连接,互斥锁模式会将压力集中在少数工作进程上,进而因工作进程负载不均而导致 QPS 下降。
③ 套接字分片(Socket Sharding)
套接字分片是由内核提供的一种分配机制,该机制允许每个工作进程都有一组相同的监听套接字。当有外部连接请求时,由内核决定哪个工作进程的套接字监听可以接收连接。这有效避免了惊群现象的发生,相比互斥锁机制提高了多核系统的性能。该功能需要在配置 listen 指令时启用 reuseport 参数。
Nginx 1.11.3 以后的版本中互斥锁模式默认是关闭的,由于 Nginx 的工作进程数量有限,且 Nginx 通常会在高并发场景下应用,很少有空闲的工作进程,所以惊群现象的影响不大。无调度模式因少了争抢互斥锁的处理,在高并发场景下可提高系统的响应能力。套接字分片模式则因为由 Linux 内核提供进程的调度机制,所以性能最好。
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 时间片,从而能够及时处理其他工作。通过事件驱动的异步非阻塞机制(见下图),使大量任务可以在工作进程中得到高效处理,以应对高并发的连接和请求。
![异步非阻塞机制](/upload/202204/26/202204260712524933.gif)
图:异步非阻塞机制
2、工作流机制
Nginx 在处理客户端请求时,每个连接仅由一个进程进行处理,每个请求仅运行在一个工作流中,工作流被划分为多个阶段(见下图),请求在不同阶段由功能模块进行数据处理,处理结果异常或结束则将结果返回客户端,否则将进入下一阶段。工作进程维护工作流的执行,并通过工作流的状态推动工作流完成请求操作的闭环。
![Nginx 工作流](/upload/202204/26/202204260712525401.gif)
图:Nginx 工作流
1) HTTP 请求处理阶段
HTTP 请求的处理过程可分为 11 个阶段,HTTP 请求处理阶段如下表所示。
阶段标识 | 阶段说明 |
NGX_HTTP_POST_READ_PHASE |
读取请求阶段,会进行 HTTP 请求头的读取和解析处理 |
NGX_HTTP_SERVER_REWRITE_PHASE |
server 重定向阶段,会在 URI进入location路由前修改 URI 的内容,进行重定向处理 |
NGX_HTTP_FIND_CONFIG_PHASE |
URI 匹配阶段,URI 进行 location 匹配处理,该阶段不支持外部模块引入 |
NGX_HTTP_REWRITE_PHASE |
rewrite 重写阶段,对 URI 执行 rewrite 规则修改处理 |
NGX_HTTP_POST_REWRITE_PHASE |
rewrite 重写结束阶段,对 rewrite 的结果执行跳转操作并进行次数验证,超过 10 次的则认为是死循环,返回 500 错误。该阶段不支持外部模块引入 |
NGX_HTTP_PREACCESS_PHASE |
访问控制前阶段,进行连接数、单 IP 访问频率等的处理 |
NGX_HTTP_ACCESS_PHASE |
访问控制阶段,进行用户认证、基于源 IP 的访问控制等处理 |
NGX_HTTP_POST_ACCESS_PHASE |
访问控制结束阶段,对访问控制的结果进行处理,如向用户发送拒绝访问等响应。该阶段不支持外部模块引入 |
NGX_HTTP_PRECONTENT_PHASE |
访问内容前阶段,对目标数据进行内容检验等操作。以前的版本称为 NGX_HTTP_TRY_FILES_PHASE,try_files 和 mirror 功能在这个阶段被执行 |
NGX_HTTP_CONTENT_PHASE |
访问内容阶段,执行读取本地文件,返回响应内容等操作 |
NGX_HTTP_LOG_PHASE |
日志记录阶段,处理完请求,进行日志记录 |
HTTP 请求处理阶段可以让每个模块仅在该阶段独立完成该阶段可实现的功能,而整个 HTTP 请求则是由多个功能模块共同处理完成的。
2) TCP/UDP 处理阶段
TCP/UDP 会话一共会经历 7 个处理阶段,每个 TCP/UDP 会话会自上而下地按照7个阶段进行流转处理,每个处理阶段的说明如下表所示。
阶段标识 | 阶段说明 |
Post-accept |
接收客户端连接请求后的第一阶段。模块 ngx_stream_realip_module 在这个阶段被调用 |
Pre-access |
访问处理前阶段。模块 ngx_stream_limit_conn_module 在这个阶段被调用 |
Access |
访问处理阶段。模块 ngx_stream_access_module 在这个阶段被调用 |
SSL |
TLS/SSL 处理阶段。模块 ngx_stream_ssl_module 在这个阶段被调用 |
Preread |
数据预读阶段。将 TCP/UDP 会话数据的初始字节读入预读缓冲区,以允许 ngx_stream_ssl_preread_module 之类的模块在处理之前分析 |
Content |
数据数据处理阶段。通常将 TCP/UDP 会话数据代理到上游服务器,或将模块 ngx_stream_return_module 指定的值返回给客户端 |
Log |
记录客户端会话处理结果的最后阶段。模块 ngx_stream_log_module 在这个阶段被调用 |
Nginx 功能模块就是根据不同的功能目的,按照模块开发的加载约定嵌入不同的处理阶段的。
3、模块化
Nginx 一直秉持模块化的理念,其模块化的架构中,除了少量的主流程代码,都是模块。模块化的设计为 Nginx 提供了高度的可配置、可扩展、可定制特性。模块代码包括核心模块和功能模块两个部分:核心模块负责维护进程的运行、内存及事件的管理;功能模块则负责具体功能应用的实现,包括路由分配、内容过滤、网络及磁盘数据读写、代理转发、负载均衡等操作。Nginx 的高度抽象接口使用户很容易根据开发规范进行模块开发,有很多非常实用的第三方模块被广泛使用。
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) 动态模块
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_module=dynamic
编译后,模块文件以 so 文件的形式独立存储于 Nginx 的 modules 文件夹中。动态模块编译如下图所示。
![动态模块编译](/upload/202204/26/202204260712526265.gif)
图:动态模块编译
在不同编译配置选项下,Nginx 在编译时会因为某些结构字段未被使用而不会将其编译到代码中,因此就会出现不同编译配置选项的动态模块无法加载的问题。为解决这个问题,Nginx 在编译配置选项中提供了
--with-compat
选项,在进行 Nginx 及动态模块编译配置时如果使用了该选项,在相同版本的 Nginx 代码下,动态模块即使与 Nginx 执行文件的其他编译配置选项不同,也可以被 Nginx 执行文件加载。启用兼容参数编译的示例如下:
./configure --with-compat --with-http_xslt_module=dynamic
可以在配置文件中使用 load_module 指令加载动态模块,示例如下:
load_module "modules/ngx_http_xslt_filter_module.so";
这篇关于weixueyuan-nginx的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!