目录
[1 Web 服务基础介绍](#1 Web 服务基础介绍)
[1.1 Web 服务介绍](#1.1 Web 服务介绍)
[1.1.1 Apache 经典的 Web 服务端](#1.1.1 Apache 经典的 Web 服务端)
[1.1.2 Nginx-高性能的 Web 服务端](#1.1.2 Nginx-高性能的 Web 服务端)
[1.1.3 用户访问体验和性能](#1.1.3 用户访问体验和性能)
[1.1.4 服务端 I/O 流程](#1.1.4 服务端 I/O 流程)
[1.2 I/O 模型](#1.2 I/O 模型)
[1.2.1 I/O 模型相关概念](#1.2.1 I/O 模型相关概念)
[1.2.2 网络 I/O 模型](#1.2.2 网络 I/O 模型)
[1.2.3 五种 IO 对比](#1.2.3 五种 IO 对比)
[1.2.4 I/O 的具体实现方式](#1.2.4 I/O 的具体实现方式)
[2 Nginx 架构和安装](#2 Nginx 架构和安装)
[2.1 Nginx 概述](#2.1 Nginx 概述)
[2.1.1 Nginx 介绍](#2.1.1 Nginx 介绍)
[2.1.2 Nginx 功能介绍](#2.1.2 Nginx 功能介绍)
[2.1.3 基础特性](#2.1.3 基础特性)
[2.2 Nginx 架构和进程](#2.2 Nginx 架构和进程)
[2.2.1 Nginx 进程结构](#2.2.1 Nginx 进程结构)
[2.2.2 Nginx 进程间通信](#2.2.2 Nginx 进程间通信)
[2.2.3 Nginx 启动和 HTTP 连接建立](#2.2.3 Nginx 启动和 HTTP 连接建立)
[2.3 Nginx 模块介绍](#2.3 Nginx 模块介绍)
[2.4 核心配置详细](#2.4 核心配置详细)
[2.4.1 配置文件说明](#2.4.1 配置文件说明)
[2.4.3 全局配置](#2.4.3 全局配置)
[3 实验案例和示例](#3 实验案例和示例)
[3.1 Nginx 的安装与升级](#3.1 Nginx 的安装与升级)
[3.1.1 Nginx版本和安装方式](#3.1.1 Nginx版本和安装方式)
[3.1.2 Nginx 编译安装](#3.1.2 Nginx 编译安装)
[3.1.3 设置环境变量和启动文件](#3.1.3 设置环境变量和启动文件)
[3.1.4 平滑升级和回滚](#3.1.4 平滑升级和回滚)
[3.2 高并发配置](#3.2 高并发配置)
[3.3 建立首个web站点](#3.3 建立首个web站点)
[3.4 root与alias](#3.4 root与alias)
[3.5 用户认证访问](#3.5 用户认证访问)
[3.6 自定义错误页面](#3.6 自定义错误页面)
[3.7 自定义日志](#3.7 自定义日志)
[3.8 文件检测](#3.8 文件检测)
[3.9 长连接配置](#3.9 长连接配置)
[3.10 下载服务器部署](#3.10 下载服务器部署)
[3.11 nginx状态页](#3.11 nginx状态页)
[3.12 网页压缩功能](#3.12 网页压缩功能)
[3.13 Nginx 变量使用](#3.13 Nginx 变量使用)
[3.14 rewrite模块](#3.14 rewrite模块)
[3.14.1 if指令](#3.14.1 if指令)
[3.14.2 set 指令](#3.14.2 set 指令)
[3.14.3 break 指令](#3.14.3 break 指令)
[3.14.4 return 指令](#3.14.4 return 指令)
[3.14.5 rewrite指令](#3.14.5 rewrite指令)
[3.14.6 rewrite实现全站加密](#3.14.6 rewrite实现全站加密)
[3.14.7 不存在页面重定向](#3.14.7 不存在页面重定向)
[3.15 防盗链](#3.15 防盗链)
[3.16 反向代理实现动静分离](#3.16 反向代理实现动静分离)
[3.17 反向代理缓存功能](#3.17 反向代理缓存功能)
[3.18 四层负载](#3.18 四层负载)
[3.19 部署fastcgi泵整合nginx](#3.19 部署fastcgi泵整合nginx)
[3.20 利用memcache加速php](#3.20 利用memcache加速php)
[3.21 memcache实现高速缓存](#3.21 memcache实现高速缓存)
[3.22 nginx二次开发版本](#3.22 nginx二次开发版本)
1 Web****服务基础介绍
正常情况下的单次 web 服务访问流程:
1.1 Web 服务介绍
1.1.1 Apache 经典的 Web 服务端
Apache 起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发,目前经历了两大版本分别是 1.X和2.X ,其可以通过 编译安装 实现特定的功能
1)Apache prefork 模型
- 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
- 每个子进程有一个独立的线程响应用户请求
- 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
- 是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程 , 占用资源较多,并发性差 , 不适用于高并发场景

2)Apache worker 模型
- 有一个控制进程,启动多个子进程
- 每个子进程里面包含固定的线程
- 使用线程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,
- 由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比 prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用 keepalive 的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用( 该问题在prefork模式下,同样会发生 )
3)Apache event 模型
Apache 中最新的模式, 2012 年发布的 apache 2.4.X 系列正式支持 event 模型 , 属于事件驱动模型 (epoll),每个进程响应多个请求,在现在版本里的已经是稳定可用的模式。
-
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题(某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
-
event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
-
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理 keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制

1.1.2 Nginx- 高性能的 Web 服务端
官网地址 ++www.nginx.org++
Nginx 历经十几年的迭代更新( ++https://nginx.org/en/CHANGES++ ),目前功能已经非常完善且运行稳 定,另外Nginx 的版本分为开发版、稳定版和过期版, nginx 以功能丰富著称,它即可以作为 http 服务器,也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求。
支持 FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http 或者 TCP 的负载均衡 (1.9 版本以上且开启stream 模块 ) 等功能,并且支持第三方的功能扩展。
天猫淘宝京东小米 163 新浪等一线互联网公司都在用 Nginx 或者进行二次开发
基于 Nginx 的工作场景:
1.1.3 用户访问体验和性能
1)用户访问体验统计
互联网存在用户速度体验的 1-3-10原则 ,即 1 秒最优, 1-3 秒较优, 3~10 秒比较慢, 10 秒以上用户无法接受。用户放弃一个产品的代价很低,只是换一个URL 而已。
全球最大搜索引擎 Google :慢 500ms = 20% 将放弃访问。
全球最大的电商零售网站亚马逊:慢 100ms = 1% 将放弃交易
有很多研究都表明,性能对用户的行为有很大的影响:
79% 的用户表示不太可能再次打开一个缓慢的网站
47% 的用户期望网页能在 2 秒钟以内加载
40% 的用户表示如果加载时间超过三秒钟,就会放弃这个网站
页面加载时间延迟一秒可能导致转换损失 7% ,页面浏览量减少 11%
8秒定律 :用户访问一个网站时,如果等待网页打开的时间超过 8 秒,会有超过 30% 的用户放弃等待
2)影响用户体验的因素
据说马云在刚开始创业在给客户演示时,打开一个网站花了不到四个小时
影响用户体验的因素:
- 客户端
- 客户端硬件配置
- 客户端网络速率
- 客户端与服务端距离
- 服务器
- 服务端网络速率
- 服务端硬件配置
- 服务端架构设计
- 服务端应用程序工作模式
- 服务端并发数量服务端响应文件大小及数量 buffer cache
- 服务端I/O压力1.2.4 服务端 I/O 流程
1.1.4 服务端 I/O 流程
I/O 在计算机中指 Input/Output , IOPS (Input/Output Per Second) 即每秒的输入输出量 ( 或读写次数 ) ,是衡量磁盘性能的主要指标之一。IOPS 是指单位时间内系统能处理的 I/O 请求数量,一般以每秒处理的 I/O请求数量为单位, I/O 请求通常为读或写数据操作请求。
一次完整的 I/O 是用户空间的进程数据与内核空间的内核数据的报文的完整交换,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy 到用户空间的进程内存当中,所以简单说 I/O 就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。
服务器的 I/O
- 磁盘I/O
- 网络I/O : 一切皆文件,本质为对socket文件的读写
1)磁盘 I/O
磁盘 I/O 是进程向内核发起系统调用,请求磁盘上的某个资源比如是 html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间
2) 网络 I/O
网络通信就是网络协议栈到用户空间进程的 IO 就是网络 IO
网络 I/O 处理过程 - 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
- 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
- 返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)
不论磁盘和网络 I/O
每次 I/O ,都要经由两个阶段:
第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
1.2 I/O 模型
1.2.1 I/O 模型相关概念
同步 / 异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
同步: synchronous ,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事
情是否处理完成
异步: asynchronous ,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞 / 非阻塞:关注调用者在等待结果返回之前所处的状态
阻塞: blocking ,指 IO 操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂
起,干不了别的事情。
非阻塞: nonblocking ,指 IO 操作被调用后立即返回给用户一个状态值,而无需等到 IO 操作彻底完
成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。

1.2.2 网络 I/O 模型
阻塞型、非阻塞型、复用型、信号驱动型、异步
1)阻塞型 I/O 模型( blocking IO )
- 阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
- 用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作
- 用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线
- 程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
优点:程序简单,在阻塞等待数据期间进程 / 线程挂起,基本不会占用 CPU 资源
缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较apache 的preforck使用的是这种模式。
同步阻塞:程序向内核发送 I/O 请求后一直等待内核响应,如果内核处理请求的 IO 操作不能立即返回 , 则进程将一直等待并不再接受新的请求,并由进程轮询查看I/O 是否完成,完成后进程将 I/O 结果返回给 Client,在 IO 没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看 I/O 是否完成,这种方式简单,但是比较慢,用的比较少。
2)非阻塞型 I/O 模型 (nonblocking IO)
用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即 "轮询"机制存在两个问题:如果有大量文件描述符都要等,那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长,程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完成。
查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返回一个 EWOULDBLOCK 错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准备好了,所以这时数据会被复制到应用进程缓冲区,于是 recvfrom 成功返回数据
当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实际使用很少
3)多路复用 I/O 型 (I/O multiplexing)
上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理
多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自的IO,即复用同一个线程
一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用,从而实现多路复用IO
I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个
process就可以同时处理多个网络连接的IO。
它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
当用户进程调用了select,那么整个进程会被block,而同时,kernel会"监视"所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
Apache prefork是此模式的select,worker是poll模式。
IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示"我要监视这些fd是否有IO事件发生,有了就告诉程序处理"IO多路复用一般和NIO一起使用的。NIO和IO多路复用是相对独立的。NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时还是当前线程被卡住。IO多路复用和NIO是要配合一起使用才有
实际意义
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程多个连接共用一个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达 时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只能监控一个IO虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率IO多路复用是最常使用的IO模型,但是其异步程度还不够"彻底",因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO模型,而非真正的异步IO
优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述符一个线程),这样可以大大节省系统资源
缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加
IO 多路复用适用如下场合:
- 当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
- 当一个客户端同时处理多个套接字时,此情况可能的但很少出现
- 当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
- 当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
- 当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
4)信号驱动式 I/O 模型 (signal-driven IO)
信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知进程。
调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主
程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO信 号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进程所需要的数据从内核空间拷贝到用户空间
此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞
当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。
优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率
缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。
5)异步 I/O 模型 (asynchronous IO)
异步I/O 与信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把等待上菜的时间也给省了
相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。
信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了
优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠
缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求
Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、libuv。
异步非阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。
1.2.3 五种 IO 对比
这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优。前四种属于同步 I/O ,因为其中真正的 I/O操作(recvfrom) 将阻塞进程 / 线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配

1.2.4 I/O 的具体实现方式
1) I/O 常见实现
Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统版本上面的实现方式不尽相同,主要有以下实现方式:
1、select:
select库是在linux和windows平台都基本支持的事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
2、poll:
在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
3、epoll:
epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮询检查这个表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的"活跃"的描述符进行操作。
4、kqueue:
用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮询操作提供效率。
5、Iocp:
Windows系统上的实现方式,对应第5种(异步I/O)模型。
6、rtsig:
不是一个常用事件驱动,最大队列1024,不是很常用
7、/dev/poll:
用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发 Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。
8、eventport:
该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防止内核崩溃等情况的发生。
2)常用 I/O 模型比较
Select :
POSIX所规定,目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理
缺点
单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定 FD_SETSIZE,再重新编译内核实现,但是这样也会造成效率的降低单个进程可监视的fd数量被限制,默认是1024,修改此值需要重新编译内核对socket是线性扫描,即采用轮询的方法,效率较低select 采取了内存拷贝方法来实现内核将 FD 消息通知给用户空间,这样一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大
poll :
本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态其没有最大连接数的限制,原因是它是基于链表来存储的大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义poll特点是"水平触发",如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd select是边缘触发即只通知一次
epoll :
在Linux 2.6内核中提出的select和poll的增强版本支持水平触发LT和边缘触发ET,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,并且只会通知一次使用"事件"的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知
优点 :
没有最大并发连接的限制:能打开的FD的上限远大于1024(1G的内存能监听约10万个端口),具体查看/proc/sys/fs/file-max,此值和系统内存大小相关
效率提升:非轮询的方式,不会随着FD数目的增加而效率下降;只有活跃可用的FD才会调用callback函 数,即epoll最大的优点就在于它只管理"活跃"的连接,而跟连接总数无关
内存拷贝,利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减少复制开销
总结 :
1、epoll只是一组API,比起select这种扫描全部的文件描述符,epoll只读取就绪的文件描述符,再加入基于事件的就绪通知机制,所以性能比较好
2、基于epoll的事件多路复用减少了进程间切换的次数,使得操作系统少做了相对于用户任务来说的无用功。
3、epoll比select等多路复用方式来说,减少了遍历循环及内存拷贝的工作量,因为活跃连接只占总并发连接的很小一部分。
实例:最大并发连接数和内存有直接关系
1.3 零拷贝
1.3.1 零拷贝介绍
传统 Linux中 I/O 的问题

传统的 Linux 系统的标准 I/O 接口(read、write)是基于数据拷贝的,也就是数据都是copy_to_user或者 copy_from_user,这样做的好处是,通过中间缓存的机制,减少磁盘 I/O 的操作,但是坏处也很明显,大量数据的拷贝,用户态和内核态的频繁切换,会消耗大量的 CPU 资源,严重影响数据传输的性能,统计表明,在Linux协议栈中,数据包在内核态和用户态之间的拷贝所用的时间甚至占到了数据包整个处理流程时间的57.1%
什么是零拷贝
零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做到"0"拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化
1.3 .2 零拷页相关技术
1)MMAP ( Memory Mapping )
mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问。
mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。
内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输

上面左图为传统读写,右图为MMAP.两者相比mmap要比普通的read系统调用少了一次copy的过程。因为read调用,进程是无法直接访问kernel space的,所以在read系统调用返回前,内核需要将数据从内核复制到进程指定的buffer。但mmap之后,进程可以直接访问mmap的数据(page cache)。
2 )SENDFILE
3) DMA 辅助的 SENDFILE
2 Nginx 架构和安装
2.1 Nginx 概述
2.1.1 Nginx 介绍
Nginx:engine X ,2002年开发,分为社区版和商业版(nginx plus )
Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器
解决C10K问题(10K Connections)
Nginx官网:++http://nginx.org++
nginx的其它的二次发行版:
- Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始,Tengine成为一个开源项目官网: ++http://tengine.taobao.org/++
- OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台,章亦春团队开发,官网:++http://openr++ ++esty.org/cn/++
2.1.2 Nginx 功能介绍
- 静态的web资源服务器html,图片,js,css,txt等静态资源
- http/https协议的反向代理
- 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
- tcp/udp协议的请求转发(反向代理)
- imap4/pop3协议的反向代理
2.1.3 基础特性
- 模块化设计,较好的扩展性
- 高可靠性
- 支持热部署:不停机更新配置文件,升级版本,更换日志文件
- 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
- event-driven,aio,mmap,sendfile
2.1.4 Web 服务相关的功能
- 虚拟主机(server)
- 支持 keep-alive 和管道连接(利用一个连接做多次请求)
- 访问日志(支持基于日志缓冲提高其性能)
- url rewirte
- 路径别名
- 基于IP及用户的访问控制
- 支持速率限制及并发数限制
- 重新配置和在线升级而无须中断客户的工作进程
2.2 Nginx 架构和进程

2.2.1 Nginx 进程结构
web 请求处理机制
- 多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求
- 多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
Nginx 是多进程组织模型,而且是一个由 Master 主进程和 Worker 工作进程组成。
主进程 (master process) 的功能:
- 对外接口:接收外部的操作(信号)
- 对内转发:根据外部的操作的不同,通过信号管理 Worker
- 监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
- 读取Nginx 配置文件并验证其有效性和正确性
- 建立、绑定和关闭socket连接
- 按照配置生成、管理和结束工作进程
- 接受外界指令,比如重启、升级及退出服务器等指令
- 不中断服务,实现平滑升级,重启服务并应用新的配置
- 开启日志文件,获取文件描述符
- 不中断服务,实现平滑升级,升级失败进行回滚处理
- 编译和处理perl脚本
工作进程( worker process )的功能: - 所有 Worker 进程都是平等的
- 实际处理:网络请求,由 Worker 进程处理
- Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源
- 增加上下文切换的损耗
- 接受处理客户的请求
- 将请求依次送入各个功能模块进行处理
- I/O调用,获取响应数据
- 与后端服务器通信,接收后端服务器的处理结果
- 缓存数据,访问缓存索引,查询和调用缓存数据
- 发送请求结果,响应客户的请求
- 接收主程序指令,比如重启、升级和退出等

2.2.2 Nginx 进程间通信
工作进程是由主进程生成的,主进程使用fork()函数(进程镜像),在Nginx服务器启动过程中主进程根据配置文件决定启动工作进程的数量,然后建立一张全局的工作表用于存放当前未退出的所有的工作进程,主进程生成工作进程后会将新生成的工作进程加入到工作进程表中,并建立一个单向的管道并将其传递给工作进程,该管道与普通的管道不同,它是由主进程指向工作进程的单向通道,包含了主进程向工作进程发出的指令、工作进程ID、工作进程在工作进程表中的索引和必要的文件描述符等信息。
主进程与外界通过信号机制进行通信,当接收到需要处理的信号时,它通过管道向相关的工作进程发送正确的指令,每个工作进程都有能力捕获管道中的可读事件,当管道中有可读事件的时候,工作进程就会从管道中读取并解析指令,然后采取相应的执行动作,这样就完成了主进程与工作进程的交互。
worker进程之间的通信原理基本上和主进程与worker进程之间的通信是一样的,只要worker进程之间能够取得彼此的信息,建立管道即可通信,但是由于worker进程之间是完全隔离的,因此一个进程想要知道另外一个进程的状态信息,就只能通过主进程来实现。
为了实现worker进程之间的交互,master进程在生成worker进程之后,在worker进程表中进行遍历,将该新进程的PID以及针对该进程建立的管道句柄传递给worker进程中的其他进程,为worker进程之间的通信做准备,当worker进程1向worker进程2发送指令的时候,首先在master进程给它的其他worker进程工作信息中找到2的进程PID,然后将正确的指令写入指向进程2的管道,worker进程2捕获到管道中的事件后,解析指令并进行相关操作,这样就完成了worker进程之间的通信。
另外worker进程可以通过共享内存来通讯的,比如upstream中的zone,或者limit_req、limit_conn中的zone等。操作系统提供了共享内存机制

2.2.3 Nginx 启动和 HTTP 连接建立

- Nginx 启动时,Master 进程,加载配置文件
- Master 进程,初始化监听的 socket
- Master 进程,fork 出多个 Worker 进程
- Worker 进程,竞争新的连接,获胜方通过三次握手,建立 Socket 连接,并处理请求
2.3 Nginx 模块介绍
nginx 有多种模块
- 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能
- 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如:端口配置、网页编码设置、 HTTP响应头设置等等
- 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash
- 多媒体传输、解析 GeoIP 请求、网络传输压缩、安全协议 SSL 支持等
- 邮件服务模块:主要用于支持 Nginx 的邮件服务,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
- Stream服务模块: 实现反向代理功能,包括TCP协议代理
- 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等

2.4 核心配置详细
2.4.1 配置文件说明
nginx 官方帮助文档: ++http://nginx.org/en/docs/++
Nginx 的配置文件的组成部分:
- 主配置文件:nginx.conf
- 子配置文件: include conf.d/*.conf
- fastcgi, uwsgi,scgi 等协议相关的配置文件
- mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
nginx配置文件格式说明
- 配置文件由指令与指令块构成
- 每条指令以;分号结尾,指令与值之间以空格符号分隔
- 可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐
- 指令块以{}大括号将多条指令组织在一起,且可以嵌套指令块
- include语句允许组合多个配置文件以提升可维护性
- 使用#符号添加注释,提高可读性
- 使用$符号使用变量
- 部分指令的参数支持正则表达式
Nginx 主配置文件的配置指令方式:
主配置文件结构:四部分
bash
main block:主配置段,即全局配置段,对http,mail都有效
#事件驱动相关的配置
event {
...
}
#http/https 协议相关配置段
http {
...
}
#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
...
}
#stream 服务器相关配置段
stream {
...
}
2.4.2默认****配置文件格式说明
bash
#全局配置端,对全局生效,主要设置nginx的启动用户/组,启动的工作进程数量,工作模式,Nginx的PID路
径,日志路径等。
user nginx nginx;
worker_processes 1; #启动工作进程数数量
----块分隔符----
events { #events #设置快,主要影响nginx服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型 #处理请求,每个工作进程可以同时支持的最大连接数,是否开启对多工作进程下的网络连接进行序列化等。
worker_connections 1024; #设置单个nginx工作进程可以接受的最大并发,
#作为web服务器的时候最大并发数为 #worker_connections * worker_processes
#作为反向代理的时候为(worker_connections * worker_processes)/2
}
----块分隔符----
http { #http块是Nginx服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都 #可以在这设置,http块可以包含多个server块,而一个server块中又可以包含多个location块
#server块可以配置文件引入、MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和 #单个链接的请求上限等。
include mime.types;
default_type application/octet-stream;
sendfile on; #作为web服务器的时候打开sendfile加快静态文件传输,指定是否使用
#sendfile系统调用来传输文件
#sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作)
#从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝,
#硬盘 >> kernel buffer (快速拷贝到kernelsocketbuffer) >>协议栈。
keepalive_timeout 65; #长连接超时时间,单位是秒
server { #设置一个虚拟机主机,可以包含自己的全局快,同时也可以包含多个location模块
#比如本虚拟机监听的端口、本虚拟机的名称和IP配置,多个server可以使用一个端口比如都使用 #80端口提供web服务
listen 80; #配置server监听的端口
server_name localhost; #本server的名称,当访问此名称的时候nginx会调用当前serevr
内部的配置进程匹配。
location / { #location其实是server的一个指令,为nginx服务器提供比较
多而且灵活的指令
#都是在location中体现的,主要是基于nginx接受到的请求字符
串
#对用户请求的UIL进行匹配,并对特定的指令进行处理
#包括地址重定向、数据缓存和应答控制等功能都是在这部分实现
#另外很多第三方模块的配置也是在location模块中配置。
root html; #相当于默认页面的目录名称,默认是安装目录的相对路径,可以使
用绝对路径配置。
index index.html index.htm; #默认的页面文件名称
}
error_page 500 502 503 504 /50x.html; #错误页面的文件名称
location = /50x.html { #location处理对应的不同错误码的页面定
义到/50x.html
#这个跟对应其server中定义的目录下。
root html; #定义默认页面所在的目录
}
}
#和邮件相关的配置
#mail {
# ...
# } mail 协议相关配置段
#tcp代理配置,1.9版本以上支持
#stream {
# ...
# } stream 服务器相关配置段
#导入其他路径的配置文件
#include /apps/nginx/conf.d/*.conf
}
2.4.3 全局配置
Main 全局配置段常见的配置指令分类
- 正常运行必备的配置
- 优化性能相关的配置
- 用于调试及定位问题相关的配置
- 事件驱动相关的配置
全局配置说明
bash
user nginx nginx; #启动Nginx工作进程的用户和组
worker_processes [number | auto]; #启动Nginx工作进程的数量,一般设为和CPU核心数相同
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
#将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进
程独占以一核心CPU,但是可以保证此进程不运行在其他核心上,这就极大减少了nginx的工作进程在不同的
cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务
器的性能。
CPU MASK: 00000001:0号CPU
00000010:1号CPU
10000000:7号CPU
#示例
worker_cpu_affinity 0001 0010 0100 1000;第0号---第3号CPU
worker_cpu_affinity 0101 1010;
#示例
worker_processes 4;
worker_cpu_affinity 00000010 00001000 00100000 10000000;
[root@centos8 ~]# ps axo pid,cmd,psr | grep nginx
31093 nginx: master process /apps 1
34474 nginx: worker process 1
34475 nginx: worker process 3
34476 nginx: worker process 5
34477 nginx: worker process 7
#错误日志记录配置,语法:error_log file [debug | info | notice | warn | error | crit
| alert | emerg]
#error_log logs/error.log;
#error_log logs/error.log notice;
error_log /usr/local/nginx/logs/error.log error;
#pid文件保存路径
pid /usr/local/nginx/logs/nginx.pid;
worker_priority 0; #工作进程优先级,-20~20(19)
worker_rlimit_nofile 65536; #所有worker进程能打开的文件数量上限,
#包括:Nginx的所有连接(例如与代理服务器的连接等)
#而不仅仅是与客户端的连接
#另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制
#最好与ulimit -n 或者limits.conf的值保持一致,
#修改pam限制
[root@Nginx ~]# sudo -u nginx ulimit -n
1024
[root@Nginx ~]# vim /etc/security/limits.conf
* - nofile 100000
[root@Nginx ~]# sudo -u nginx ulimit -n
100000
daemon off; #前台运行Nginx服务用于测试、docker等环境。
master_process off|on; #是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为on
events {
worker_connections 65535; #设置单个工作进程的最大并发连接数
use epoll; #使用epoll事件驱动,
#Nginx支持众多的事件驱动,
#比如:select、poll、epoll,只能设置在events模块中设置
accept_mutex on; #on为同一时刻一个请求轮流由work进程处理,
#而防止被同时唤醒所有worker
#避免多个睡眠进程被唤醒的设置,默认为off
#新请求会唤醒所有worker进程,此过程也称为"惊群"
#因此nginx刚安装完以后要进行适当的优化。建议设置为on
multi_accept on; #on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接
#此指令默认为off,
#即默认为一个工作进程只能一次接受一个新的网络连接
#打开后几个同接受多个。建议设置为on
}
3 实验案例和示例
实验环境介绍
webservera #eth0 172.25.254.10
RS1 #eth0 172.25.254.100
RS2 #eth0 172.25.254.200
火墙全部关闭
3.1 Nginx 的****安装与升级
3.1.1 Nginx****版本和安装方式
Nginx 版本
- Mainline version 主要开发版本,一般为奇数版本号,比如1.19
- Stable version 当前最新稳定版,一般为偶数版本,如:1.20
- Legacy versions 旧的稳定版,一般为偶数版本,如:1.18
Nginx 安装可以使用 yum 或源码安装,但是推荐使用源码编译安装 - yum的版本比较旧
- 编译安装可以更方便自定义相关路径
- 使用源码编译可以自定义相关功能,更方便业务的上的使用
3.1.2 Nginx****编译安装
编译器介绍
源码安装需要提前准备标准的编译器,GCC的全称是(GNU Compiler collection),其有GNU开发,并以 GPL即LGPL许可,是自由的类UNIX即苹果电脑Mac OS X操作系统的标准编译器,因为GCC原本只能处理C语 言,所以原名为GNU C语言编译器,后来得到快速发展,可以处理C++,Fortran,pascal,objective C, java以及Ada等其他语言,此外还需要Automake工具,以完成自动创建Makefile的工作,Nginx的一些模块需要依赖第三方库,比如: pcre(支持rewrite),zlib(支持gzip模块)和openssl(支持ssl模块) 等。
编译安装 Nginx
官方源码包下载地址:https://nginx.org/en/download.html
编译安装示例:
bash
[root@webserver ~]# ls
anaconda-ks.cfg nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
#这里先下载nginx-1.24.0.tar.gz,为后面平滑升级示例做准备
[root@webserver ~]# tar zxf nginx-1.24.0.tar.gz #解压
[root@webserver ~]# cd nginx-1.24.0/
[root@webserver nginx-1.24.0]# useradd -s /sbin/nologin -M nginx #创建用户
[root@webserver nginx-1.24.0]# dnf install gcc pcre-devel zlib-devel openssl-devel -y #下载源码编译所需前置
[root@webserver nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
--user=nginx \ # 指定nginx运行用户
--group=nginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip
[root@webserver nginx-1.24.0]# make && make install #静候编译完成
[root@webserver nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin
conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他
的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params
两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀
去掉即可。
html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web
文件是默认的错误页面提示页面。
logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比
如/var/logs/nginx里面。
sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
3.1.3 设置环境变量和启动文件
bash
###设置环境变量,以便后续直接使用nginx指令
[root@webserver nginx-1.24.0]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@webserver nginx-1.24.0]# source ~/.bash_profile
[root@webserver nginx-1.24.0]# nginx -V #查看版本信息
nginx version: nginx/1.24.0
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
###设置启动脚本
[root@webserver nginx-1.24.0]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[root@webserver nginx-1.24.0]# systemctl daemon-reload
[root@webserver nginx-1.24.0]# systemctl start nginx.service

3.1.4 平滑升级和回滚
有时候我们需要对 Nginx 版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
- 将旧Nginx二进制文件换成新Nginx程序文件(注意先备份)
- 向master进程发送USR2信号
- master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin
- master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进程的PID存放至新生成的pid文件nginx.pid
- 向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止
- 向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件
- 如果发现升级有问题,可以回滚∶向老master发送HUP,向新master发送QUIT
示例:
bash
###平滑升级
[root@webserver nginx-1.24.0]# cd ~
[root@webserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
[root@webserver ~]# tar zxf nginx-1.26.1.tar.gz
[root@webserver ~]# cd nginx-1.26.1/
[root@webserver nginx-1.26.1]# ./configure --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
[root@webserver nginx-1.26.1]# make
[root@webserver nginx-1.26.1]# ll objs/nginx /usr/local/nginx/sbin/nginx
-rwxr-xr-x 1 root root 5752872 Aug 11 16:44 objs/nginx
-rwxr-xr-x 1 root root 5678264 Aug 11 16:21 /usr/local/nginx/sbin/nginx
#复制旧的nginx
[root@webserver nginx-1.26.1]# cd /usr/local/nginx/sbin/
[root@webserver sbin]# cp nginx nginx.24
[root@webserver sbin]# ls
nginx nginx.24
[root@webserver sbin]# cp -f ~/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin #新的取代旧的
[root@webserver sbin]# ps aux|grep nginx
root 34849 0.0 0.0 9864 928 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 34850 0.0 0.2 13760 4708 ? S 16:36 0:00 nginx: worker process
root 37919 0.0 0.1 6408 2176 pts/0 S+ 16:51 0:00 grep --color=auto nginx
[root@webserver sbin]# kill -USR2 34849
[root@webserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 34850 0.0 0.2 13760 4708 ? S 16:36 0:00 nginx: worker process
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 37921 0.0 0.2 13768 4628 ? S 16:52 0:00 nginx: worker process
root 37923 0.0 0.1 6408 2164 pts/0 S+ 16:52 0:00 grep --color=auto nginx
#USR2平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
#回收旧版本
root@webserver sbin]# kill -WINCH 34849
[root@webserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 37921 0.0 0.2 13768 4628 ? S 16:52 0:00 nginx: worker process
root 37932 0.0 0.1 6408 2184 pts/0 S+ 16:54 0:00 grep --color=auto nginx
#测试
[root@webserver sbin]# curl -I localhost
...
Server: nginx/1.26.1
...
###回滚
[root@webserver sbin]# cp nginx nginx.26 #此时的nginx是新版本的
[root@webserver sbin]# ls
nginx nginx.24 nginx.26
[root@webserver sbin]# mv nginx.24 nginx
mv: overwrite 'nginx'? y
[root@webserver sbin]# kill -HUP 34849
[root@webserver sbin]# kill -WINCH 37920
[root@webserver sbin]# ps aux|grep nginx
root 34849 0.0 0.1 9864 2528 ? Ss 16:36 0:00 nginx: master process /usr/local/nginx/sbin/nginx
root 37920 0.0 0.3 9872 6092 ? S 16:52 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 37958 0.0 0.2 13760 4708 ? S 17:00 0:00 nginx: worker process
root 37977 0.0 0.1 6408 2180 pts/0 S+ 17:01 0:00 grep --color=auto nginx
[root@webserver sbin]# curl -I localhost
...
Server: nginx/1.24.0
...
注意:后面的实验使用的是新装的nginx1.26,是将/usr/local/nginx删掉后重新编译的
3.2 高并发配置
bash
[root@webserver ~]# cd /usr/local/nginx
[root@webserver nginx]# vim conf/nginx.conf
...
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 100000;
...
events {
...
worker_connections 100000;
use epoll;
...
}
[root@webserver nginx]# vim /etc/security/limits.conf
* - nproc 100000
* - nofile 100000
[root@webserver nginx]# ulimit -n 100000
#测试
[root@webserver nginx]# dnf install httpd-tools-2.4.57-5.el9.x86_64
[root@webserver nginx]# echo webservera > html/index.html
[root@webserver nginx]# systemctl restart nginx
[root@webserver nginx]# ab -c 5000 -n 10000 http://172.25.254.10/
...
Complete requests: 10000
Failed requests: 0
...
3.3 建立首个web站点
bash
#配置网站
[root@webserver nginx]# vim conf/nginx.conf
http{
...
include/apps/nginx/conf/conf.d/*.conf; #在http里的最后添加,不然会导致前面的指令无法生效
}
[root@webserver nginx]# mkdir /usr/local/nginx/conf.d
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
}
#创建访问的文件
[root@webserver nginx]# mkdir /web/html -p
[root@webserver nginx]# echo web_html > /web/html/index.html
#添加域名解析
[root@webserver nginx]# vim /etc/hosts
172.25.254.10 webserver.timinglee.org www.timinglee.org
#测试
[root@webserver nginx]# curl www.timinglee.org
webservera
补充:

3.4 root与alias
root :指定 web 的家目录,在定义 location 的时候,文件的绝对路径等于 root+locati
alias :定义路径别名,会把访问的路径重新定义到其指定的路径 , 文档映射的另一种机制 ; 仅能用于
location 上下文 , 此指令使用较少
bash
#
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
location /root {
root /web/;
}
location /alias {
alias /web/root;
}
}
[root@webserver nginx]# nginx -s reload
#测试
[root@webserver nginx]# mkdir /web/root/
[root@webserver nginx]# echo 无论这么访问都是root > /web/root/index.html
[root@webserver nginx]# curl www.timinglee.org/root/
无论这么访问都是root
[root@webserver nginx]# curl www.timinglee.org/alias/
无论这么访问都是root
3.5 用户认证访问
bash
[root@webserver nginx]# htpasswd -cmb conf/.htpasswd admin lee
Adding password for user admin
[root@webserver nginx]# htpasswd -mb conf/.htpasswd lee lee
Adding password for user lee
[root@webserver nginx]# mkdir /web/auth/
[root@webserver nginx]# echo login > /web/auth/index.html
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
location /auth {
root /web/
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/conf/.htpasswd";
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl www.timinglee.org/auth/ -u lee:lee
login
3.6 自定义错误页面
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_page 500 502 503 504 /error.html;
location /error.html {
root /web/error/;
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# mkdir /web/error
[root@webserver nginx]# echo errorlll > /web/error/error.html
[root@webserver nginx]# curl www.timinglee.org/aa
errorlll
3.7 自定义日志
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# mkdir /var/log/nginx -p
[root@webserver nginx]# touch /var/log/nginx/access.log
[root@webserver nginx]# touch /var/log/nginx/error.log
#测试
[root@webserver nginx]# curl 172.25.254.10
webservera
[root@webserver nginx]# curl www.timinglee.org
...
[root@webserver nginx]# cat /var/log/nginx/error.log
2025/08/11 19:13:22 [error] 41686#0: *12245 directory index of "/web/" is forbidden, client: 172.25.254.10, server: www.timinglee.org, request: "GET / HTTP/1.1", host: "www.timinglee.org"
[root@webserver nginx]# cat /var/log/nginx/access.log
172.25.254.10 - - [11/Aug/2025:19:13:22 +0800] "GET / HTTP/1.1" 403 153 "-" "curl/7.76.1"
3.8 文件检测
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_page 404 /web/error/error.html
try_files $uri.html $uri.html $uri/index.html /web/default.html;
location /error {
root /web/;
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl www.timinglee.org/a/
defautl
3.9 长连接配置
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
keepalive_timeout 65; #65秒后自动断开
#连接请求3次后断开
#开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断
开,第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时
间。
keepalive_requests 3;
#浏览器收到的服务器返回的报文
#如果设置为0表示关闭会话保持功能,将如下显示:
#Connection:close 浏览器收到的服务器返回的报文
error_log /var/log/nginx/error.log;
}
[root@webserver nginx]# dnf install telnet -y
[root@webserver nginx]# telnet 172.25.254.10 80
Trying 172.25.254.10...
Connected to 172.25.254.10.
Escape character is '^]'.
GET / HTTP/1.1
Host: www.timinglee.org
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:13 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: keep-alive
ETag: "6899c683-9"
Accept-Ranges: bytes
web_html
GET / HTTP/1.1
Host: www.timinglee.org
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:38 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: keep-alive
ETag: "6899c683-9"
Accept-Ranges: bytes
web_html
GET / HTTP/1.1
Host: www.timinglee.org
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 13:27:46 GMT
Content-Type: text/html
Content-Length: 9
Last-Modified: Mon, 11 Aug 2025 10:31:31 GMT
Connection: close
ETag: "6899c683-9"
Accept-Ranges: bytes
web_html
Connection closed by foreign host.
[root@webserver nginx]#
3.10 下载服务器部署
bash
#创建下载文件
[root@webserver nginx]# mkdir /web/download
[root@webserver nginx]# dd if=/dev/zero of=/web/download/lee bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 3.28797 s, 159 MB/s
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
location /download {
root /web/;
autoindex on; #自动索引功能
autoindex_exact_size on; #计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb、mb、gb)
autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间
limit_rate 1024k; #限速,默认不限速
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl www.timinglee.org/download/
<html>
<head><title>Index of /download/</title></head>
<body>
<h1>Index of /download/</h1><hr><pre><a href="../">../</a>
<a href="lee">lee</a> 11-Aug-2025 21:37 524288000
</pre><hr></body>
</html>

3.11 nginx状态页
- 基于nginx 模块 ngx_http_stub_status_module 实现,
- 在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
- 否则配置完成之后监测会是提示法错误
注意 : 状态页显示的是整个服务器的状态 , 而非虚拟主机的状态
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
location /status {
stub_status;
auth_basic "status page"; #开启状态页
auth_basic_user_file "/usr/local/nginx/conf/.htpasswd"; #用户认证文件
}
}
[root@webserver nginx]# nginx -s reload


3.12 网页压缩功能
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
#启用或禁用gzip压缩,默认关闭
gzip on;
#压缩比由低到高从1到9,默认为1,值越高压缩后文件越小,但是消耗cpu比较高。基本设定未4或者5
gzip_comp_level 4;
#禁用IE6 gzip功能,早期的IE6之前的版本不支持压缩
gzip_disable "MSIE [1-6]\.";
#gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
#启用压缩功能时,协议的最小版本,默认HTTP/1.1
gzip_http_version 1.1;
#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;
gzip_buffers 16 8k;
#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
# gzip_types ...;
#如果启用压缩,是否在响应报文首部插入"Vary: Accept-Encoding",一般建议打开
gzip_vary on;
#预压缩,即直接从磁盘找到对应文件的gz后缀的式的压缩文件返回给用户,无需消耗服务器CPU
#注意: 来自于ngx_http_gzip_static_module模块
gzip_static on;
}
[root@webserver nginx]# nginx -s reload
cp /usr/local/nginx/logs/access.log /web/html/data.html
[root@webserver nginx]# curl --head --compressed 172.25.254.10/data.html
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 14:15:49 GMT
Content-Type: text/html
Last-Modified: Mon, 11 Aug 2025 14:13:09 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"6899fa75-4bc2d0"
Content-Encoding: gzip
3.13 Nginx 变量使用
- nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
- 变量可以分为内置变量和自定义变量
- 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
bash
[root@webserver nginx]# cd ~
[root@webserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.26.1
echo-nginx-module-0.63.tar.gz nginx-1.24.0.tar.gz nginx-1.26.1.tar.gz
[root@webserver ~]# tar zxf echo-nginx-module-0.63.tar.gz
[root@webserver ~]# rm -rf nginx-1.26.1
[root@webserver ~]# nginx -V
nginx version: nginx/1.26.1
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
[root@webserver ~]# tar zxf nginx-1.26.1.tar.gz
[root@webserver ~]# cd nginx-1.26.1/
#在之前的./configure里加上 --add-module=/root/echo-nginx-module-0.63
[root@webserver nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/root/echo-nginx-module-0.63
[root@webserver nginx-1.26.1]# cd objs/
[root@webserver objs]# cp -p nginx /usr/local/nginx/sbin/nginx
[root@webserver objs]# cp /usr/local/nginx/conf/nginx.conf /mnt
[root@webserver objs]# cp -rp /usr/local/nginx/conf.d /mnt
[root@webserver objs]# rm -rf /usr/local/nginx/
[root@webserver objs]# cd ..
[root@webserver nginx-1.26.1]# make install
[root@webserver nginx-1.26.1]# cp /mnt/nginx.conf /usr/local/nginx/conf/nginx.conf
cp: overwrite '/usr/local/nginx/conf/nginx.conf'? y
[root@webserver nginx-1.26.1]# cp -r /mnt/conf.d/ /usr/local/nginx/
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
location /test {
default_type text/html;
echo $remote_addr;
echo $args;
echo $document_root;
echo $document_uri;
echo $host;
echo $http_user_agent;
}
}
[root@webserver nginx]# systemctl restart nginx.service
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl www.timinglee.org/test
172.25.254.10
/web/html
/test
www.timinglee.org
curl/7.76.1
bash
#官方文档 http://nginx.org/en/docs/varindex.html
#常用内置变量
$remote_addr;
#存放了客户端的地址,注意是客户端的公网IP
$args;
#变量中存放了URL中的所有参数
#例如:https://search.jd.com/Search?keyword=手机&enc=utf-8
#返回结果为: keyword=手机&enc=utf-8
$is_args
#如果有参数为? 否则为空
$document_root;
#保存了针对当前资源的请求的系统根目录,例如:/webdata/nginx/timinglee.org/lee。
$document_uri;
#保存了当前请求中不包含参数的URI,注意是不包含请求的指令
#比如:http://lee.timinglee.org/var?\id=11111会被定义为/var
#返回结果为:/var
$host;
#存放了请求的host名称
limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_port;
#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口
$remote_user;
#已经经过Auth Basic Module验证的用户名
$request_body_file;
#做反向代理时发给后端服务器的本地资源的名称
$request_method;
#请求资源的方式,GET/PUT/DELETE等
$request_filename;
#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,
#如:webdata/nginx/timinglee.org/lee/var/index.html
$request_uri;
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,
#例如:/main/index.do?id=20190221&partner=search
$scheme;
#请求的协议,例如:http,https,ftp等
$server_protocol;
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr;
#保存了服务器的IP地址
$server_name;
#虚拟主机的主机名
$server_port;
#虚拟主机的端口号
$http_user_agent;
#客户端浏览器的详细信息
$http_cookie;
#客户端的所有cookie信息
$cookie_<name>
#name为任意请求报文首部字部cookie的key名
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,name的对应的首部字段名需要为小写,如果有
横线需要替换为下划线
#示例:
echo $http_user_agent;
echo $http_host;
$sent_http_<name>
#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有
问题
echo $sent_http_server;
$arg_<name>
#此变量存放了URL中的指定参数,name为请求url中指定的参数
echo $arg_id;
3.14 rewrite模块
- Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
- 此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
- rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
- 比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
- 另外还可以在一定程度上提高网站的安全性
官方文档 : https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
3.14.1 if指令
用于条件匹配判断,并根据条件判断结果选择不同的 Nginx 配置,可以配置在 server 或 location 块中进行配置,Nginx 的 if 语法仅能使用 if 做单次判断,不支持使用 if else 或者 if elif 这样的多重判断,用法如下:
3.14.2 set****指令
指定 key 并给其定义一个变量,变量可以调用 Nginx 内置变量赋值给 key
另外 set 定义格式为 set $key value , value 可以是 text, variables 和两者的组合。
3.14.3 break****指令
- 用于中断当前相同作用域(location)中的其他Nginx配置
- 与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
- 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
- Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置
- 该指令可以在server块和locationif块中使用
注意 : 如果 break 指令在 location 块中后续指令还会继续执行 , 只是不执行 ngx_http_rewrite_module
模块的指令 , 其它指令还会执行
3.14.4 return****指令
return 用于完成对请求的处理,并直接向客户端返回响应状态码,比如 : 可以指定重定向 URL( 对于特殊重定向状态码,301/302 等 ) 或者是指定提示文本内容 ( 对于特殊状态码 403/500 等 ) ,处于此指令后的所有配置都将不被执行,return 可以在 server 、 if 和 location 块进行配置
3.14.5 rewrite指令
通过正则表达式的匹配来改变 URI ,可以同时存在一个或多个指令,按照顺序依次对 URI 进行匹配,rewrite主要是针对用户请求的 URL 或者是 URI 做具体处理
语法格式:
rewrite regex replacement [flag];
rewrite 将用户请求的 URI 基于 regex 所描述的模式进行检查,匹配到时将其替换为表达式指定的新的 URI
注意 :如果在同一级配置块中存在多个 rewrite 规则,那么会自下而下逐个检查 ; 被某条件规则替换完成 后,会重新一轮的替换检查,隐含有循环机制, 但不超过 10 次 ; 如果超过,提示 500 响应码, [flag] 所表示的 标志位用于控制此循环机制
如果替换后的 URL 是以 http:// 或 https:// 开头,则替换结果会直接以重定向返回给客户端 , 即永久重定向301
rewrite flag 使用介绍
- 利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型
- 跳转型指由客户端浏览器重新对新地址进行请求
- 代理型是在WEB服务器内部实现跳转
rewrite格式 :rewrite regex replacement [flag]

bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
location /test {
root /web/;
rewrite ^/test http://www.timinglee.org;
}
location /break/ {
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1 ;
}
location /last/ {
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1 ;
}
location /test1 {
return 666 "test1";
}
location /test2 {
return 22 "test2";
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# mkdir /web/html/{test1,test2,break,last} -p
[root@webserver nginx]# echo this is test1 > /web/html/test1/index.html
[root@webserver nginx]# echo this is test2 > /web/html/test2/index.html
[root@webserver nginx]# curl -L www.timinglee.org/test
web_html
[root@webserver nginx]# curl -L www.timinglee.org/break/index.html
this is test1
[root@webserver nginx]# curl -L www.timinglee.org/last/index.html
test1[root@webserver nginx]#
3.14.6 rewrite实现全站加密
案例:基于通信安全考虑公司网站要求全站 https ,因此要求将在不影响用户请求的情况下将 http 请求全部自动跳转至 https,另外也可以实现部分 location 跳转
bash
[root@webserver nginx]# mkdir /usr/local/nginx/certs
[root@webserver nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/timinglee.org.key -x509 -days 365 -out
/usr/local/nginx/certs/timinglee.org.crt
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
ssl_certificate /usr/local/nginx/certs/timinglee.org.crt;
ssl_certificate_key /usr/local/nginx/certs/timinglee.org.key;
ssl_session_cache shared:sslcache:1m;
ssl_session_timeout 5m;
location / {
if ($scheme = http ){
rewrite / https://$host;
}
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl -I http://www.timinglee.org
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.1
Date: Mon, 11 Aug 2025 15:37:58 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://www.timinglee.org
3.14.7 不存在页面重定向
bash
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
if (!-e $request_filename) {
rewrite .* http://www.timinglee.org
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# curl -L www.timinglee.org/asdaw/
web_html
3.15 防盗链
防盗链基于客户端携带的 referer 实现, referer 是记录打开一个页面之前记录是从哪个页面跳转过来的标 记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer 就是之前的那个网站域名,正常的 referer 信息有以下几种:
防盗链的实现
bash
#RS1模拟盗链客户端
[root@RS1 ~]# dnf install httpd
[root@RS1 ~]# vim /var/www/html/index.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.timinglee.org/images/lee.png" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.timinglee.org>狂点老李</a>出门见喜</p>
</body>
</html>
[root@RS1 ~]# vim /etc/hosts
172.25.254.10 www.timinglee.org
[root@RS1 ~]# systemctl start httpd
#准备好照片
[root@webserver nginx]# mkdir /web/html/image
[root@webserver nginx]# cp ~/test.png /web/html/image/

实现防盗链
bash
#webserver
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
index index.html;
error_log /var/log/nginx/error.log;
location / {
valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;
if ($invalid_referer){
return 404;
}
}
}
[root@webserver nginx]# nginx -s reload

3.16 反向代理实现动静分离
反向代理: reverse proxy ,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的 一种方式,这是用的比较多的一种方式。
Nginx 除了可以在企业提供高性能的 web 服务之外,另外还可以将 nginx 本身不具备的请求通过某种预 定义的协议转发至其它服务器处理,不同的协议就是Nginx 服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能
bash
ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass
#等指令引用的后端服务器分组
ngx_stream_proxy_module: #将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module: #将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理
#官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
proxy_pass; #用来设置将客户端请求转发给的后端服务器的主机
#可以是主机名(将转发至后端服务做为主机头首部)、IP地址:端口的方式
#也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持
#示例:
proxy_pass http://172.25.254.30:8080; #8080后面无uri,即无 / 符号,
#需要将location后面url 附加到proxy_pass指定的url后面
#此行为类似于root
#proxy_pass指定的uri不带斜线将访问的/web
#等于访问后端服务器
proxy_pass http://172.25.254.40:8080/; #8080后面有uri,即有 / 符号
#相当于置换,即访问/web时实际返回proxy_pass后面uri内容
#此行为类似于alias
#proxy_pass指定的uri带斜线
#等于访问后端服务器的
#http://172.25.254.40:8080/index.html
#内容返回给客户端
#如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能
使用uri
#即不能有/ ,用户请求时传递的uri将直接附加至后端服
proxy_hide_header field; #用于nginx作为反向代理的时候
#在返回给客户端http响应时
#隐藏后端服务器相应头部的信息
#可以设置在http,server或location块务器之后
proxy_pass_header field; #透传
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数
#如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
proxy_pass_request_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
proxy_set_header;
#可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
proxy_connect_timeout time;
#配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒
用法如下:proxy_connect_timeout 6s;
#60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码
proxy_read_timeout time;
#配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s
proxy_send_timeout time;
#配置nginx项后端服务器或服务器组发起write请求后,等待的超时 时间,默认60s
proxy_http_version 1.0;
#用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0
proxy_ignore_client_abort off;
#当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器、会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并立即记录499日志,默认为off。
逻辑调用关系:

访问逻辑图:
同构代理:用户不需要其他程序的参与,直接通过 http 协议或者 tcp 协议访问后端服务器
异构代理:用户访问的资源时需要经过处理后才能返回的,比如 php , python ,等等,这种访问资源需要经过处理才能被访问
示例:
bash
#RS1
[root@RS1 ~]# echo 172.25.254.100 > /var/www/html/index.html
#RS2
[root@RS2 ~]# systemctl restart httpd
[root@RS2 ~]# mkdir /var/www/html/php/
[root@RS2 ~]# vim /var/www/html/php/index.php
<?php
phpinfo ();
?>
#webserver
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
error_log /var/log/nginx/error.log;
location / {
proxy_pass http://172.25.254.100:80;
}
location ~ \.(php|jpg|gif) {
proxy_pass http://172.25.254.200:80;
}
}
[root@webserver nginx]# nginx -s reload


3.17 反向代理缓存功能
bash
proxy_cache zone_name | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义
proxy_cache_key string;
#缓存中用于"键"的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;时长,定义在http{...}中
proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2 #定义缓存目录结构层次
#1:2:2可以生成
keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata
(如:使用次数)
#一般1M可存放8000个左右的key
inactive=120s #缓存有效时间
max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 |
http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默认是off
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
示例:
bash
#webserver
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /web/html;
error_log /var/log/nginx/error.log;
location / {
proxy_pass http://www.lee.org;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 10m;
proxy_cache_valid any 1m;
}
location ~ \.(php|jpg|gif)$ {
proxy_pass http://172.25.254.200:80;
}
}
[root@webserver nginx]# vim conf/nginx.conf
http{
...
proxy_cache_path /usr/local/nginx/cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=10g;
...
}
#加缓存之前
[root@RS2 ~]# ab -c 500 -n 10000 http://www.timinglee.org/index.html
Time per request: 1846.322 [ms] (mean)
#加缓存之后
[root@RS2 ~]# ab -c 500 -n 10000 http://www.timinglee.org/index.html
Time per request: 230.727 [ms] (mean)
3.18 四层负载
bind的四层负载
bash
#RS1 和 RS2
[root@RS1 ~]# dnf install bind -y
[root@RS1 ~]# vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };
...
// allow-query { localhost; };
...
dnssec-validation no;
}
[root@RS1 ~]# cd /var/named
[root@RS1 named]# cp -p named.localhost "timinglee.org.zone"
[root@RS1 named]# vim timinglee.org.zone #RS2下面的ip是200
$TTL 1D
@ IN SOA dns.timinglee.org. root.timinglee.org. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns.timinglee.org.
dns A 172.25.254.100
[root@RS1 named]# vim /etc/named.rfc1912.zones
...
zone "timinglee.org" IN {
type master;
file "timinglee.org.zone";
allow-update { none; };
};
...
[root@RS1 named]# systemctl restart named
#webserver
[root@webserver nginx]# mkdir tcp.d
[root@webserver nginx]# vim tcp.d/dns.conf
[root@webserver nginx]# vim conf/nginx.conf
include "/usr/local/nginx/tcp.d/*.conf" ; #不能写在http语句块中
[root@webserver nginx]# vim tcp.d/dns.conf
stream {
upstream dns {
server 172.25.254.100:53 max_fails=3 fail_timeout=5;
server 172.25.254.200:53 max_fails=3 fail_timeout=5;
}
server {
listen 53 udp;
proxy_pass dns;
}
}
[root@webserver nginx]# nginx -s reload
测试:

mariadb的四层负载
bash
#RS1和RS2
[root@RS1 named]# vim /etc/my.cnf.d/mariadb-server.cnf
...
[mysqld]
server-id =100 #RS2的是200
...
[root@RS1 named]# systemctl start mariadb.service
[root@RS1 named]# mysql -e "create user lee@'%' identified by 'lee';"
[root@RS1 named]# mysql -e "grant select on *.* to lee@'%';"
[root@webserver nginx]# vim tcp.d/dns.conf #stream只能有一个,写在别的文件也不行
stream {
upstream mariadb {
server 172.25.254.100:3306 max_fails=3 fail_timeout=5;
server 172.25.254.200:3306 max_fails=3 fail_timeout=5;
}
server {
listen 3306;
proxy_pass mariadb;
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# mysql -ulee -plee -h172.25.254.10 -e"select @@server_id;"
+-------------+
| @@server_id |
+-------------+
| 100 |
+-------------+
[root@webserver nginx]# mysql -ulee -plee -h172.25.254.10 -e"select @@server_id;"
+-------------+
| @@server_id |
+-------------+
| 200 |
3.19 部署fastcgi泵整合nginx
CGI 的由来:
最早的 Web 服务器只能简单地响应浏览器发来的 HTTP 请求,并将存储在服务器上的 HTML 文件返回给浏 览器,也就是静态html 文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技术,比如像php(1995 年 ) 、 java(1995) 、 python(1991) 语言开发的网站,但是 nginx/apache 服务器并不能直接运行 php 、 java 这样的文件, apache 实现的方式是打补丁,但是 nginx 缺通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx 并回收进程,最后 nginx 在返回给客户端,那这个约定就是通用网关接口(common gateway interface ,简称 CGI) , CGI (协议) 是 web 服务器和外部应用程序之间的接口标准,是cgi 程序和 web 服务器之间传递信息的标准化接口。
为什么会有 FastCGI ?
CGI 协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server每收到一个请求都会创建一个CGI 进程, PHP 解析器都会解析 php.ini 文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI 进程都会执行这些操作,所以效率很低,而 FastCGI 是用来提高 CGI 性能的,FastCGI 每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。什么是PHP-FPM ?PHP-FPM(FastCGI Process Manager:
- FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
- 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server的请求
- worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
FastCGI 配置指令
Nginx 基于模块 ngx_http_fastcgi_module 实现通过 fastcgi 协议将指定的客户端请求转发至 php-fpm 处理,其配置指令如下:
bash
fastcgi_pass address:port;
#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in
location
fastcgi_index name;
#fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义
key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
Nginx默认配置示例:
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为
prefix/conf
}
示例:
编译安装更方便自定义参数或选项,所以推荐大家使用源码编译
官方网站: www.php.net
bash
###源码编译php
[root@webserver ~]# cd ~
[root@webserver ~]# dnf install -y bzip2 systemd-devel libxml2-devel sqlite-devel
[root@webserver ~]# dnf install -y libpng-devel libcurl-devel
[root@webserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.26.1.tar.gz php-8.3.9
echo-nginx-module-0.63 nginx-1.24.0.tar.gz oniguruma-6.9.6-1.el9.6.x86_64.rpm php-8.3.9.tar.gz
echo-nginx-module-0.63.tar.gz nginx-1.26.1 oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm test.png
#两个包,不一样
[root@webserver ~]# dnf update oniguruma-6.9.6-1.el9.6.x86_64.rpm
[root@webserver ~]# dnf install oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm
[root@webserver ~]# tar zxf php-8.3.9.tar.gz
[root@webserver ~]# cd php-8.3.9/
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --with-curl --with-iconv --with-mhash --with-zlib --with-openssl --enable-mysqlnd --with-mysqli --with-pdo-mysql --disable-debug --enable-sockets --enable-soap --enable-xml --enable-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd
[root@webserver ~]# make && make install
#等待ing~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[root@webserver php-8.3.9]# cd /usr/local/php/
[root@webserver php]# cd etc/
[root@webserver etc]# cp -p php-fpm.conf.default php-fpm.conf
[root@webserver etc]# vim php-fpm.conf
pid = run/php-fpm.pid #指定pid文件存放位置,给代码去掉注释
[root@webserver etc]# cd php-fpm.d/
[root@webserver php-fpm.d]# cp www.conf.default www.conf -p
[root@webserver php-fpm.d]# vim www.conf
listen = 0.0.0.0:9000
[root@webserver php-fpm.d]# cd ~/php-8.3.9/
[root@webserver php-8.3.9]# cp php.ini-production /usr/local/php/etc/php-ini
[root@webserver php-8.3.9]# cd sapi/fpm/
[root@webserver fpm]# cp php-fpm.service /lib/systemd/system
[root@webserver fpm]# cd /lib/systemd/system
[root@webserver system]# vim php-fpm.service
...
#ProtectSystem=full
[root@webserver system]# systemctl daemon-reload
[root@webserver system]# systemctl enable --now php-fpm.service
[root@webserver nginx]# cd /usr/local/nginx/
[root@webserver nginx]# vim html/index.php
<?php
phpinfo ();
?>
[root@webserver nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
error_log /var/log/nginx/error.log;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
[root@webserver nginx]# nginx -s reload

3.20 利用memcache加速php
软件下载: ++http://pecl.php.net/package/memcache++

bash
###memcache整合php
[root@webserver nginx]# dnf install memcached -y
[root@webserver nginx]# vim /etc/sysconfig/memcached
...
OPTIONS="-l 0.0.0.0,::1"
[root@webserver nginx]# systemctl enable --now memcached.service
[root@webserver ~]# ls
anaconda-ks.cfg nginx-1.24.0 oniguruma-6.9.6-1.el9.6.x86_64.rpm test.png
echo-nginx-module-0.63 nginx-1.24.0.tar.gz oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm
echo-nginx-module-0.63.tar.gz nginx-1.26.1 php-8.3.9
memcache-8.2.tgz nginx-1.26.1.tar.gz php-8.3.9.tar.gz
[root@webserver ~]# tar zxf memcache-8.2.tgz
[root@webserver ~]# cd memcache-8.2/
[root@webserver memcache-8.2]# cp example.php memcache.php /usr/local//nginx/html/
[root@webserver memcache-8.2]# cd /usr/local/nginx/
[root@webserver nginx]# ls html/
50x.html example.php index.html index.php memcache.php
[root@webserver nginx]# vim html/memcache.php
...
define('ADMIN_USERNAME','admin'); // Admin Username
define('ADMIN_PASSWORD','lee'); // Admin Password
#$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array
$MEMCACHE_SERVERS[] = '127.0.0.1:11211'; // add more as an array
...
###php整合memcache
[root@webserver nginx]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/bin:/usr/local/php/sbin
[root@webserver nginx]# source ~/.bash_profile
[root@webserver nginx]# cd ~/memcache-8.2/
[root@webserver memcache-8.2]# dnf install autoconf -y
[root@webserver memcache-8.2]# phpize
[root@webserver memcache-8.2]# ./configure && make && make install
[root@webserver memcache-8.2]# cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
[root@webserver no-debug-non-zts-20230831]# ls
memcache.so opcache.so
[root@webserver no-debug-non-zts-20230831]# systemctl restart php-fpm.service
[root@webserver no-debug-non-zts-20230831]# cd /usr/local/php/etc/
[root@webserver etc]# vim php-ini
...
975 extension=memcache
...
990 date.timezone = Asia/Shangha
...

3.21 memcache实现高速缓存
在我们安装的 nginx 中默认不支持 memc 和 srcache 功能,需要借助第三方模块来让 nginx 支持此功能,所以nginx 需要重新编译
bash
[root@webserver nginx]# mv conf.d /mnt
[root@webserver nginx]# mv conf/nginx.conf /mnt
[root@webserver nginx]# rm -rf /usr/local/nginx/
[root@webserver nginx]# cd ~
[root@webserver ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@webserver ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@webserver ~]# cd nginx-1.26.1/
[root@webserver nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33 --add-module=/root/echo-nginx-module-0.63
[root@webserver nginx]# cp /mnt/nginx.conf conf/nginx.conf
[root@webserver nginx]# vim conf.d/vhost.conf
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name www.timinglee.org;
error_log /var/log/nginx/error.log;
location /memc {
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
set $memc_key $query_string; #使用内置变量$query_string来作为key
set $memc_exptime 300; #缓存失效时间300秒
memc_pass memcache;
}
location ~ \.php$ {
set $key $uri$args; #设定key的值
srcache_fetch GET /memc $key; #检测mem中是否有要访问的php
srcache_store PUT /memc $key; #缓存为加载的php数据
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
[root@webserver nginx]# nginx -s reload
[root@webserver nginx]# vim html/index.php
#测试
[root@webserver nginx]# ab -n1000 -c50 http://www.timinglee.org/index.php
...
Complete requests: 1000
Failed requests: 0 #not have 失败
...
3.22 nginx二次开发版本

- Nginx 是俄罗斯人发明的, Lua 是巴西几个教授发明的,中国人章亦春把 LuaJIT VM 嵌入到 Nginx 中,实现了 OpenResty 这个高性能服务端解决方案
- OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
- OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将Nginx有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
- OpenResty 由于有功能强大且方便的的API,可扩展性更强,如果需要实现定制功能,OpenResty是个不错的选择
官网: ++http://openresty.org/cn/++
bash
[root@webserver nginx]# systemctl stop nginx.service
[root@webserver nginx]# cd ~
[root@webserver ~]# rm -rf /usr/local/nginx/
[root@webserver ~]# ls
anaconda-ks.cfg memc-nginx-module-0.20.tar.gz package.xml
echo-nginx-module-0.63 nginx-1.26.1 php-8.3.9
echo-nginx-module-0.63.tar.gz nginx-1.26.1.tar.gz php-8.3.9.tar.gz
memcache-8.2 oniguruma-6.9.6-1.el9.6.x86_64.rpm srcache-nginx-module-0.33
memcache-8.2.tgz oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm srcache-nginx-module-0.33.tar.gz
memc-nginx-module-0.20 openresty-1.25.3.1.tar.gz
[root@webserver ~]# tar zxf openresty-1.25.3.1.tar.gz
[root@webserver ~]# cd openresty-1.25.3.1/
[root@webserver openresty-1.25.3.1]# dnf -y install gcc pcre-devel openssl-develperl
[root@webserver openresty-1.25.3.1]# useradd -r -s /sbin/nologin nginx
[root@webserver openresty-1.25.3.1]# ./configure --prefix=/usr/local/openresty --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module
[root@webserver openresty-1.25.3.1]# make && make install
[root@webserver openresty-1.25.3.1]# openresty -t
nginx: the configuration file /usr/local/openresty/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/openresty/nginx/conf/nginx.conf test is successful
[root@webserver openresty-1.25.3.1]# openresty
