企业级高性能web服务器
1 web服务基础
1.1 正常情况的单次web服务访问流程:
正常情况下,单次 Web 服务访问流程从用户在客户端发起请求开始,到最终在客户端展示内容结束,涉及客户端、网络传输、服务器端等多个环节,以下是详细过程:
1.1.1 客户端发起请求
1.用户操作与URL解析:
用户在浏览器地址栏输入网址(如https://www.example.com
),或点击网页上的链接、提交表单等操作,触发 Web 服务访问。浏览器对输入的 URL 进行解析,识别出协议(常见的有 HTTP、HTTPS)、域名(www.example.com
)、端口号(HTTP 默认 80,HTTPS 默认 443,若 URL 中未明确指定端口,浏览器会使用默认端口 )以及资源路径(如/index.html
)。
2.DNS解析:
浏览器首先检查本地的 DNS 缓存,如果缓存中有对应的域名 - IP 地址映射,则直接获取 IP 地址;若没有,就向本地 DNS 服务器发送查询请求。本地 DNS 服务器会先查询自身缓存,若未找到结果,它会向根 DNS 服务器、顶级 DNS 服务器、权威 DNS 服务器等依次进行递归或迭代查询,最终将域名解析为对应的 IP 地址(例如192.168.1.100
),并将结果返回给浏览器。
1.1.2 建立连接
1.TCP三次握手(以HTTP协议基于tcp传输为例):
- 第一次握手:客户端向服务器发送一个带有 SYN(同步序列号)标志的 TCP 报文段,该报文段中包含客户端随机生成的初始序列号(假设为 x),表示客户端请求与服务器建立连接。
- 第二次握手:服务器接收到客户端的 SYN 报文后,返回一个带有 SYN 和 ACK(确认应答)标志的 TCP 报文段。其中,ACK 标志表示对客户端 SYN 的确认,确认号为客户端初始序列号 x 加 1(即 x + 1);同时,服务器也生成自己的初始序列号(假设为 y),并将其放入 SYN 标志位中发送给客户端。
- 第三次握手:客户端收到服务器的 SYN + ACK 报文后,向服务器发送一个带有 ACK 标志的 TCP 报文段,确认号为服务器的初始序列号 y 加 1(即 y + 1),序列号为客户端的初始序列号 x 加 1(即 x + 1),表示客户端确认收到服务器的响应并完成连接建立。至此,TCP 连接成功建立。
2.TLS/SSL握手(若使用HTTPS协议):
在 TCP 连接建立后,客户端和服务器之间会进行 TLS/SSL 握手,以协商加密算法、交换公钥证书等,确保数据传输的安全性。具体步骤如下:
- 客户端发送ClientHello消息:包含客户端支持的 SSL/TLS 版本、加密算法列表、随机数等信息。
- 服务器响应ServerHello消息:服务器从客户端提供的选项中选择合适的 SSL/TLS 版本和加密算法,并返回自己的证书(包含公钥)、随机数等信息。
- 客户端验证服务器证书:客户端检查服务器证书的有效性(如证书是否过期、颁发机构是否可信等),并从中提取服务器的公钥。
- 客户端生成预主密钥:客户端使用服务器的公钥加密一个随机生成的预主密钥,并发送给服务器。
- 服务器解密预主密钥:服务器使用自己的私钥解密收到的预主密钥,然后客户端和服务器双方使用预主密钥、之前交换的随机数等信息,生成会话密钥,用于后续的数据加密传输。
具体加密原理请参考:加密(一)- 阮一峰:RSA算法原理_rsa 阮一峰-CSDN博客https://blog.csdn.net/yiguang_820/article/details/108842637
1.1.3 发送http请求
TCP 连接建立后,客户端通过该连接向服务器发送 HTTP 请求报文,请求报文主要包括:
- 请求行:包含请求方法(常见的有 GET、POST、PUT、DELETE 等,例如 GET 方法用于获取资源,POST 方法用于提交数据 )、请求的资源路径(如
/index.html
)以及 HTTP 协议版本(如 HTTP/1.1 )。 - 请求头:包含一系列键值对,提供了关于客户端、请求内容等的元信息。
- 请求体:当请求方法为 POST、PUT 等需要提交数据的方法时,请求体中包含了要发送的数据,例如表单数据(格式如
name=John&age=30
)或 JSON 格式的数据(如{"username": "John", "password": "123456"}
)。
1.1.4 服务器处理请求
- Web服务器接收与解析:Web 服务器(如 Apache、Nginx 等)在指定端口(如 80 或 443 )监听并接收客户端发送的 HTTP 请求报文,然后对请求报文进行解析,提取请求方法、资源路径等关键信息。
- 请求分发与处理:
- 静态资源请求:如果请求的是静态资源(如 HTML 文件、CSS 样式表、图片、JavaScript 脚本等),Web 服务器会根据资源路径在本地文件系统中查找对应的文件,并直接将其读取出来,准备返回给客户端。
- 动态资源请求:对于动态资源请求(例如请求一个 PHP 脚本、Python Flask 应用的接口等),Web 服务器会将请求转发给相应的应用服务器(如 PHP-FPM、Gunicorn、Tomcat 等 )。应用服务器根据请求内容执行相应的业务逻辑,这可能涉及与数据库进行交互(例如查询用户信息、获取商品列表等 )。应用服务器通过数据库驱动程序(如 MySQL Connector/Python )连接到数据库(如 MySQL、PostgreSQL 等 ),执行 SQL 查询或操作,获取或更新数据,然后将处理结果返回给 Web 服务器。
1.1.5 服务器返回响应
- 构建响应报文:Web 服务器接收到应用服务器返回的处理结果(如果是动态请求)或获取到静态资源后,构建 HTTP 响应报文。响应报文主要包括:
- 状态行:包含 HTTP 协议版本、状态码(如 200 表示请求成功,404 表示资源未找到,500 表示服务器内部错误等 )以及状态描述(如
OK
)。 - 响应头:包含一系列键值对,提供关于响应的元信息。
- 响应体:包含了实际要返回给客户端的内容,对于静态资源请求,可能是 HTML 页面、CSS 文件、图片等的二进制数据;对于动态请求,可能是 JSON 格式的数据、渲染后的 HTML 页面等。
- 发送响应:Web 服务器通过已建立的 TCP 连接,将构建好的 HTTP 响应报文发送回客户端。
1.1.6 客户端接收与渲染
- 接收响应:客户端通过 TCP 连接接收服务器发送的 HTTP 响应报文,根据响应头中的
Content-Length
等信息,确定接收数据的大小,并将数据完整地接收下来。 - 解析与渲染:
- 响应状态检测:客户端首先检查响应的状态码,如果是 200 - 299 范围内的状态码,表示请求成功;如果是其他范围的状态码,可能意味着请求失败,客户端会根据状态码的含义进行相应的处理,例如显示错误页面。
- 响应头处理:客户端解析响应头中的信息,如
Content-Type
,根据内容类型调用相应的渲染引擎。例如,如果是text/html
,则调用 HTML 渲染引擎;如果是image/jpeg
,则调用图片解码和显示模块。 - 响应体渲染:对于 HTML 页面,浏览器会构建 DOM 树,解析 CSS 样式表并应用样式,执行 JavaScript 脚本,最终在浏览器窗口中呈现出完整的网页内容;对于 JSON 数据等,客户端可能会根据业务逻辑进行数据处理和展示。
1.1.7 关闭连接
TCP四次挥手(默认情况下):
当数据传输完成后,客户端和服务器之间会进行 TCP 四次挥手来关闭连接:
- 第一次挥手:客户端发送一个带有 FIN(结束标志)的 TCP 报文段,表示客户端不再发送数据,但还可以接收数据。
- 第二次挥手:服务器接收到客户端的 FIN 报文后,返回一个带有 ACK 标志的 TCP 报文段,确认收到客户端的 FIN 请求。
- 第三次挥手:服务器发送一个带有 FIN 标志的 TCP 报文段,表示服务器也不再发送数据。
- 第四次挥手:客户端接收到服务器的 FIN 报文后,返回一个带有 ACK 标志的 TCP 报文段,确认收到服务器的 FIN 请求,至此,TCP 连接完全关闭。
HTTP长连接(若启用):在 HTTP/1.1 协议中,默认启用了 HTTP 长连接(通过Connection: keep-alive
头字段标识 ),这意味着在一次请求 - 响应完成后,TCP 连接不会立即关闭,而是可以被复用,用于后续的 HTTP 请求,这样可以减少建立和关闭连接的开销,提高性能。
1.2 web服务介绍
1.2.1 Apache经典的web服务端
1.2.1.1 Apache prefork模型
- 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
- 每个子进程有一个独立的线程响应用户请求
- 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数

1.2.1.2 Apache worker模型
- 一种多进程和多线程混合的模型
- 有一个控制进程,启动多个子进程
- 每个子进程里面包含固定的线程
- 使用线程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求
- 由于其使用了线程处理请求,因此可以承受更高的并发

1.2.1.3 Apache event模型
- Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll) 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
- 它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题(某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
- event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
- 当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力

1.2.2 nginx-高性能的web服务端
1.2.3 用户访问体验和性能
1.2.3.1 影响用户体验的因素
1.客户端:
- 客户端硬件配置
- 客户端网络速率
- 客户端与服务端距离
2.服务器:
- 服务端网络速率
- 服务端硬件配置
- 服务端架构设计
- 服务端应用程序工作模式
- 服务端并发数量,服务端响应文件大小及数量
- 服务端I/O压力
1.2.4 服务端I/O流程
- 磁盘I/O
- 网络I/O:一切皆文件,本质是对socket文件的读写
1.2.4.1 磁盘I/O
机械磁盘的寻道时间、旋转延迟和数据传输时间:寻道时间:是指磁头移动到正确的磁道上所花费的时间,寻道时间越短则I/O处理就越快,目前磁盘的寻道时间一般在3-15毫秒左右。旋转延迟:是指将磁盘片旋转到数据所在的扇区到磁头下面所花费的时间,旋转延迟取决于磁盘的转速,通常使用磁盘旋转一周所需要时间的1/2之一表示,比如7200转的磁盘平均训传延迟大约为60*1000/7200/2=4.17毫秒,公式的意思为 (每分钟60秒*1000毫秒每秒/7200转每分/2),如果是15000转的则为60*1000/15000/2=2毫秒。数据传输时间:指的是读取到数据后传输数据的时间,主要取决于传输速率,这个值等于数据大小除以传输速率,目前的磁盘接口每秒的传输速度可以达到600MB,因此可以忽略不计。常见的机械磁盘平均寻道时间值:7200转/分的磁盘平均物理寻道时间:9毫秒10000转/分的磁盘平均物理寻道时间:6毫秒15000转/分的磁盘平均物理寻道时间:4毫秒常见磁盘的平均延迟时间:7200转的机械盘平均延迟:60*1000/7200/2 = 4.17ms10000转的机械盘平均延迟:60*1000/10000/2 = 3ms15000转的机械盘平均延迟:60*1000/15000/2 = 2ms每秒最大IOPS的计算方法:7200转的磁盘IOPS计算方式:1000毫秒/(9毫秒的寻道时间+4.17毫秒的平均旋转延迟时间)=1000/13.13=75.9 IOPS10000转的磁盘的IOPS计算方式:1000毫秒/(6毫秒的寻道时间+3毫秒的平均旋转延迟时间)=1000/9=111IOPS15000转的磁盘的IOPS计算方式:15000毫秒/(4毫秒的寻道时间+2毫秒的平均旋转延迟时间)=1000/6=166.6 IOPS
1.2.4.2 网络I/O

网络I/O处理过程
- 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求
- 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成
- 返回数据,服务器将已构建好的响应再通过内核空间的网络I/O发还给客户端
不论磁盘和网络I/O
每次I/O,都要经过两个阶段:
- 将数据从文件先加载到内核内存空间(缓冲区),等待数据准备完成,时间较长
- 将数据从内核缓冲区复制到用户空间的进程内存中,时间较短
1.3 I/O模型
1.3.1 I/O模型概念
同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情
1.3.2 网络I/O模型
1.3.2.1 阻塞型I/O模型(blocking IO)
- 用户线程在内核进行IO操作时被阻塞
- 用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作
- 用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
1.3.2.2 非阻塞型I/O模型(nonblocking IO)

1.3.2.3 多路复用I/O型(I/O multiplexing)
- 上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理
- 多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自的IO,即复用同一个线程
- 一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用,从而实现多路复用IO

- 优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述符一个线程),这样可以大大节省系统资源
- 缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加
- 当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
- 当一个客户端同时处理多个套接字时,此情况可能的但很少出现
- 当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
- 当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
- 当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
1.3.2.4 信号驱动式I/O模型(signal-drven IO)
1.3.2.5 异步I/O模型(asynchronous IO)
1.3.3 五种IO对比
1.3.4 I/O的具体实现方式
1.3.4.1 I/O常见实现
- select:select库是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
- poll:在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
- epoll:epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮询检查这个表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。
- kqueue:用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮询操作提供效率。
- Iocp:Windows系统上的实现方式,对应第5种(异步I/O)模型。
- rtsig:不是一个常用事件驱动,最大队列1024,不是很常用
- /dev/poll:用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。
- eventport:该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防止内核崩溃等情况的发生。
1.3.4.2 常用I/O模型比较
select | poll | epoll | |
操作方式 | 遍历 | 遍历 | 回调 |
底层实现 | 数组 | 链表 | 哈希表 |
IO效率 | 每次调回都进行线性遍历,时间复杂度为O(n) | 同左 | 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪的fd放到rdlist里,时间复杂度O(1) |
最大连接数 | 1024(x86) 2048(x64) | 无上限 | 无上限 |
fd拷贝 | 每次调用select都需要把fd集合从用户拷贝到内核态 | 每次调用poll,都需要把fd集合从用户态拷贝到内核态 | 调用epoll_ct时拷贝进内核并保存,之后每次epoll_wait不拷贝 |
1.4 零拷贝
1.4.1 零拷贝介绍
1.4.1.1 传统Linux中I/O的问题
1.4.1.2 什么是零拷贝
1.4.2 零拷贝相关技术
1.4.2.1 MMAP(Memory Mapping)
1.4.2.2 SENDFILE
1.4.2.3 DMA辅助的SENDFILE
2 Nginx架构和安装
2.1 Nginx概述
2.1.1 nginx介绍
- Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始,Tengine成为一个开源项目官网: http://tengine.taobao.org/
- OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发,官网:http://openresty.org/cn/
2.1.2 nginx功能介绍
- 静态web资源服务器html,图片,js,css,txt等静态资源
- http/https协议的反向代理
- 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
- tcp/udp协议的转发请求转发(反向代理)
- imap4/pop3协议的反向代理
2.2.3 基础特性
- 模块化设计,较好的扩展性
- 高可靠性
- 支持热部署:不停机更新配置文件,升级版本,更换日志文件
- 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
- event-driven,aio,mmap,sendfile
2.2.4 web服务相关的功能
2.2 nginx架构和进程
- 虚拟主机(server)
- 支持keep-alive和管道连接(利用一个连接做多次请求)
- 访问日志(支持基于日志缓冲提高其性能)
- url rewirte
- 路径别名
- 基于IP及用户的访问控制
- 支持速率限制及并发数限制
- 重新配置和在线升级而无需中断客户的工作进程
2.2.2 nginx进程结构
web请求处理机制:
- 多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求
- 多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。

主进程(master)的功能:
- 对外接口:接收外部的操作(信号)
- 对内转发:根据外部的操作的不同,通过信号管理worker
- 监控:监控worker进程的运行状态,worker进程异常终止后,自动重启worker进程
- 读取nginx配置文件并验证其有效性和正确性
- 建立、绑定和关闭socker连接
- 按照配置生成、管理和结束工作进程
- 接收外界指令,如重启、升级及退出服务器等指令
- 不中断服务,实现平滑升级,重启服务并应用新的配置
- 开启日志文件,获取文件描述符
- 不中断服务,实现平滑升级,升级失败进行回滚处理
- 编译和处理perl脚本
工作进程(worker)的功能:
- 所有worker进程都是平等的
- 实际处理:网络请求,由worker进程处理
- worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源
- 增加上下文切换的损耗
- 接受处理客户的请求
- 将请求依次送入各个功能模块进行处理
- I/O调用,获取响应数据
- 与后端服务器通信,接收后端服务器的处理结果
- 缓存数据,访问缓存索引,查询和调用缓存数据
- 发送请求结果,响应客户的请求
- 接收主程序指令,比如重启、升级和退出等
2.2.3 nginx进程间通信
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.4 nginx启动和HTTP连接建立
2.3 nginx模块介绍
nginx有多种模块:
- nginx启动时,master进程加载配置文件
- master进程,初始化监听的socket
- master进程,fork出多个worker进程
- worker进程,竞争新的连接,获胜方通过三次握手,建立socket连接,并处理请求
- 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能
- 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置等
- 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
- 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
- Stream服务模块: 实现反向代理功能,包括TCP协议代理
- 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等
核心模块:core module
标准模块:HTTP模块:ngx_http_*HTTP Core modulesHTTP Optional modules # 需编译时指定Mail模块:ngx_mail_*Stream模块:ngx_stream_*
参考:勿忘初心,进无止尽!https://www.cnblogs.com/Soy-technology/p/11355597.html
2.4 nginx安装
2.4.1 nginx版本和安装方式
nginx版本:
- Mainline version 主要开发版本,一般为奇数版本号,如1.19
- Stable version 当前最稳定版本,一般为偶数版本,如1.20
- Legacy version 旧的稳定版,一般为偶数版本,如1.18
nginx安装可以使用yum或源码安装,但是推荐使用源码编译安装
2.4.2 nginx编译安装
编译器介绍:
- yum的版本比较旧
- 编译安装可以更方便自定义相关路径
- 使用源码编译可以自定义相关功能,更方便业务上的使用
2.4.2.1 编译安装nginx
官方源码包下载地址:

编译安装示例:
注意:编译安装前请确保SELinux和防火墙为关闭状态,本地yum或网络yum配置正常,网络通畅
[root@Nginx ~]# yum install gcc pcre-devel zlib-devel openssl-devel -y
[root@Nginx ~]# tar zxf nginx-1.24.0.tar.gz
[root@Nginx ~]# cd nginx-1.24.0
[root@Nginx nginx-1.24.0]# useradd -s /sbin/nologin -M nginx
[root@Nginx nginx-1.24.0]# ls # 查看是否有下面类似的文件
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \ # 指定 Nginx 的安装目录为 /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@Nginx nginx-1.24.0]# make && make install
nginx完成安装后有四个主要目录
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbinconf:保存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二进制启动脚本,可以接受不同的参数以实现不同的功能。
2.4.2.2 验证版本及编译参数
# 将 Nginx 的可执行程序目录(/usr/local/nginx/sbin)添加到系统环境变量 PATH 中
[root@Nginx ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@Nginx ~]# source ~/.bash_profile # 使刚修改的环境变量配置立即生效[root@Nginx ~]# nginx -V # 查看 Nginx 的版本信息和编译配置参数
nginx version: nginx/1.24.0
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --group=nginx --with-http_ssl_module --with-http_v2_module -
-with-http_realip_module --with-http_stub_status_module --withhttp_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --
with-stream_realip_module
2.4.2.3 使用安装完成的二进制文件nginx
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf # 编辑 Nginx 的主配置文件
[root@Nginx ~]# nginx -g "worker_processes 4;" # 启动 Nginx 服务并临时指定工作进程数为4
[root@Nginx ~]# ps aux | grep nginx # 查看当前系统中与 nginx 相关的进程状态
2.4.2.4 nginx启动文件
为 Nginx 创建一个 systemd 服务配置文件,以便通过系统服务管理器来管理 Nginx(启动、停止、开机自启等)
[root@Nginx ~]# vim /lib/systemd/system/nginx.service
[Unit]
# 服务描述信息,说明这是 Nginx HTTP 服务器和反向代理服务
Description=The NGINX HTTP and reverse proxy server
# 指定 Nginx 启动的依赖顺序,需在这些服务(系统日志、网络、远程文件系统、DNS 解析)启动之后再启动 Nginx
After=syslog.target network-online.target remote-fs.target nss-lookup.target
# 期望网络就绪后再启动nginx
Wants=network-online.target
[Service]
Type=forking # Nginx 是fork模式启动(主进程会创建子进程,主进程退出后子进程继续运行)
PIDFile=/usr/local/nginx/logs/nginx.pid # 指定Nginx主进程PID文件路径(与nginx.conf中pid配置一致)
ExecStartPre=/usr/local/nginx/sbin/nginx -t # 启动前执行的命令,nginx -t用于检查配置文件语法是否正确,确保配置无误后才启动
ExecStart=/usr/local/nginx/sbin/nginx # 启动Nginx的命令(执行 Nginx 二进制文件)
ExecReload=/usr/local/nginx/sbin/nginx -s reload # 重载配置的命令(nginx -s reload 平滑重启,不中断服务)
ExecStop=/bin/kill -s QUIT $MAINPID # 停止服务的命令
PrivateTmp=true # 为Nginx分配独立的临时目录
[Install]
WantedBy=multi-user.target
[root@Nginx ~]# systemctl daemon-reload # 重新加载systemd服务配置,使新创建的nginx.service生效
[root@Nginx ~]# systemctl start nginx # 启动Nginx服务
2.6 平滑升级和回滚
2.6.1 平滑升级流程
- 将旧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
2.6.2 平滑升级和回滚案例
[root@Nginx nginx]# tar zxf nginx-1.26.1.tar.gz
[root@Nginx nginx]# cd nginx-1.26.1/
#开始编译新版本
[root@Nginx 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
#只要make不需要make install
[root@Nginx nginx-1.26.1]# make
#查看两个版本
[root@Nginx nginx-1.26.1]# ll objs/nginx /usr/local/nginx/sbin/nginx
-rwxr-xr-x 1 root root 1239416 Jul 18 15:08 objs/nginx
-rwxr-xr-x 1 root root 5671488 Jul 18 11:41 /usr/local/nginx/sbin/nginx
#把之前的旧版的nginx命令备份
[root@Nginx ~]# cd /usr/local/nginx/sbin/
[root@Nginx sbin]# cp nginx nginx.24
#把新版本的nginx命令复制过去
[root@Nginx sbin]# cp -f /root/nginx/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin
#检测一下有没有问题
[root@Nginx sbin]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful[root@Nginx sbin]# ps aux | grep nginx # 查看进程ID
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 48733 0.0 0.2 14200 4868 ? S 14:17 0:00 nginx: worker
process
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 4868 ? S 15:41 0:00 nginx: worker
process[root@Nginx sbin]# kill -USR2 48732 #nginx worker ID
#USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进
#程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 # 此时依旧是旧版本生生效
Date: Thu, 18 Jul 2025 07:45:58 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes#回收旧版本
[root@Nginx sbin]# kill -WINCH 48732 # 减少工作进程数量,主进程保持运行,跟旧主进程ID
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 4868 ? S 15:41 0:00 nginx: worker
process
#检测版本信息
[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.26.1 #新版本生效
Date: Thu, 18 Jul 2025 07:59:45 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes#回滚
#如果升级的版本发现问题需要回滚,可以重新拉起旧版本的worker
[root@Nginx sbin]# cp nginx nginx.26
[root@Nginx sbin]# ls
nginx nginx.24 nginx.26
[root@Nginx sbin]# mv nginx.24 nginx
mv: overwrite 'nginx'? y# kill -HUP ID
# 检查新配置文件的语法是否正确(若错误则不重载,保持旧配置运行)。
# 用新配置启动新的工作进程。
# 逐步关闭旧工作进程(等待它们处理完当前请求)。
[root@Nginx sbin]# kill -HUP 48732
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52076 0.0 0.2 14208 5124 ? S 15:41 0:00 nginx: worker
process
nobody 52130 0.0 0.2 14200 4868 ? S 16:30 0:00 nginx: worker
process
[root@Nginx sbin]# kill -WINCH 52075
[root@Nginx sbin]# ps aux | grep nginx
root 48732 0.0 0.1 9868 2436 ? Ss 14:17 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
root 52075 0.0 0.3 9876 6528 ? S 15:41 0:00 nginx: master
process /usr/local/nginx/sbin/nginx
nobody 52130 0.0 0.2 14200 4868 ? S 16:30 0:00 nginx: worker
process
root 52137 0.0 0.1 221664 2176 pts/0 S+ 16:31 0:00 grep --
color=auto nginx
[root@Nginx sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 ##版本回滚完成
Date: Thu, 18 Jul 2025 08:31:51 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2025 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes
3 nginx核心配置详解
3.1 配置文件说明
nginx官方帮助文档:nginx documentationhttp://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主配置文件的配置指令方式:
main block:主配置段,即全局配置段,对http,mail都有效
#事件驱动相关的配置
event {
...
}#http/https 协议相关配置段
http {
默认的nginx.conf 配置文件格式说明
...
}#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
...
}#stream 服务器相关配置段
stream {
...
}
默认的nginx.conf配置文件格式说明:
# 全局配置端,对全局生效,主要设置nginx的启动用户/组,启动的工作进程数量,工作模式,Nginx的PID路
径,日志路径等。
user nobody; # 这里使用nginx
worker_processes 1; # 指定工作进程数量,一般设置为auto# error_log 文件路径 日志级别;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;#pid logs/nginx.pid; # 指定主进程PID文件路径# events块专门用于设置Nginx与客户端连接相关的底层参数,决定了Nginx如何处理网络事件(如接收连接、处理请求等),这些配置直接影响 Nginx 的并发处理能力
events {worker_connections 1024; # 设置单个nginx工作进程可以接受的最大并发# 作为web服务器的时候最大并发数为# worker_processes * worker_connections# 作为反向代理的时候最大并发数为# (worker_connections * worker_processes)/2
}# http块是Nginx服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都
# 可以在这设置,http块可以包含多个server块,而一个server块中又可以包含多个location块,
# server块可以配置文件引入、MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和
# 单个链接的请求上限等。
http {include mime.types;default_type application/octet-stream;#log_format main '$remote_addr - $remote_user [$time_local] "$request" '# '$status $body_bytes_sent "$http_referer" '# '"$http_user_agent" "$http_x_forwarded_for"';#access_log logs/access.log main;sendfile on; # 作为web服务器的时候打开sendfile加快静态文件传输,# 数据传输路径为:磁盘 → 内核缓存 → 网络协议栈 → 网卡,# 省略了用户态与内核态之间的拷贝,减少 CPU 占用,提升传输速度,# 被称之为零拷贝。#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65; # 长连接超时时间,单位是秒# 当客户端(如浏览器)发起请求时,若双方支持长连接,# 连接不会在单次请求后立即关闭,而是保持一段时间,供后续请求复用。# 避免每次请求都重新进行 TCP 三次握手,降低网络延迟和服务器资源消耗# 际配置时需根据业务场景(并发量、请求频率)调整,# 静态资源多的服务可适当延长,高并发动态服务可适当缩短。#gzip on;# server:设置一个虚拟机主机,可以包含自己的全局块,同时也可以包含多个location模块
# 比如本虚拟机监听的端口、本虚拟机的名称和IP配置,多个server可以使用一个端口
# 比如都使用80端口提供web服务server {listen 80; # 配置server监听的端口server_name localhost; # 本server的名称,当访问此名称的时候# nginx会调用当前serevr内部的配置进程匹配#charset koi8-r;#access_log logs/host.access.log main;# location是Nginx配置中用于匹配客户端请求URL路径的核心指令,
# 主要作用是根据请求的URL路径,定义不同的处理规则(如返回静态文件、反向代理到后端服务、
# 重定向等)。它必须嵌套在 server 块或其他 location 块中,是实现 URL 路由的关键。location / {root html; # 相当于默认页面的目录名称,默认是安装目录的相对路径,# 可以使用绝对路径配置。index index.html index.htm; # 默认的页面文件名称}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html# 当服务器返回 500、502、503、504 这些服务器端错误状态码时,# Nginx 会自动将请求重定向到 /50x.html 页面error_page 500 502 503 504 /50x.html; location = /50x.html { # location处理对应的不同错误码的页面定义到/50x.htmlroot html; # 定义默认页面所在的目录}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {# deny all;#}}# another virtual host using mix of IP-, name-, and port-based configuration##server {# listen 8000;# listen somename:8080;# server_name somename alias another.alias;# location / {# root html;# index index.html index.htm;# }#}# HTTPS server##server {# listen 443 ssl;# server_name localhost;# ssl_certificate cert.pem;# ssl_certificate_key cert.key;# ssl_session_cache shared:SSL:1m;# ssl_session_timeout 5m;# ssl_ciphers HIGH:!aNULL:!MD5;# ssl_prefer_server_ciphers on;# location / {# root html;# index index.html index.htm;# }#}
# include /usr/local/nginx/conf.d/*.conf # 导入其他路径的配置文件
}
3.2 全局配置
- main全局配置段常见的配置指令分类:
- 正常运行必备的配置
- 优化性能相关的配置
- 用于调试及定位问题相关的配置
- 事件驱动相关的配置
全局配置说明:
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号CUP
# 示例:
# worker_cpu_affinity 0001 0010 0100 1000;第0号至第3号CPU
# worker_cpu_affinity 01 10;第0号至第1号cpu
# 查看配置
[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
# a:显示所有用户的进程
# x:显示没有控制终端的进程(如后台服务进程)
# o pid,cmd,psr:自定义输出格式,仅显示三个字段
# pid:进程 ID。
# cmd:启动进程的命令(包括参数)。
# psr:进程当前运行的 CPU 核心编号error_log /usr/local/nginx/logs/error.log error; # 指定错误日志路径和错误级别pid /usr/local/nginx/logs/nginx.pid; # pid文件的保存路径worker_priority 0; # 工作进程的优先级,进程优先级范围通常为-20到19,通常保持默认0即可# 数值越小,优先级越高(如 -20 是最高优先级)# 数值越大,优先级越低(如 19 是最低优先级)# 默认值通常为 0(与系统中其他普通进程优先级相同)# 若服务器专门用于 Nginx 服务,且需要优先保障其响应速度,# 可适当降低数值(提高优先级),如 worker_priority -5;# 若 Nginx 并非服务器核心服务(如同时运行高优先级的计算任务),# 可提高数值(降低优先级),如 worker_priority 5;
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
100000daemon off; #前台运行Nginx服务用于测试、docker等环境
master_process off|on; # 是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为onevents {worker_connections 65535; # 设置单个工作进程的最大并发连接数use epoll; # 使用epoll事件驱动(Linux推荐epoll,性能最优),# Nginx支持众多的事件驱动,# 比如:select、poll、epoll,只能设置在events模块中accept_mutex on; # 惊群问题:当多个 Nginx 工作进程同时监听同一端口时,新连接到达时,# 所有工作进程会被同时唤醒竞争连接,但最终只有一个进程能获取连接,# 其余进程被唤醒后发现无连接可处理,造成 CPU 资源浪费# on时,同一时间只允许一个工作进程尝试接收新连接,避免多进程同时竞争,# 减少 CPU 无效消耗,提高连接处理效率,建议设置为onmulti_accept on; # 允许单个工作进程(worker process)一次性接收多个新连接# 减少accept()调用次数和进程唤醒频率,降低CPU上下文切换开销# 建议开启
}
3.2.1 实现nginx的高并发配置
注意:测试环境由于硬件问题,并发量写小一点(对硬件要求较高)
1.修改nginx默认配置文档
[root@server2 conf]# vim /usr/local/nginx/conf/nginx.conf
2.修改pam限制
[root@server2 conf]# vim /etc/security/limits.conf
3.查看pam是否生效
[root@server2 ~]# sudo -u nginx ulimit -n
50000
4.测试并发性能
[root@server2 ~]# ab -c 1500 -n 50000 http://192.168.36.136/index.html
-n:请求总量
-c:并发量
总共50000个请求,每次发送1500个并发
3.3 http配置块
# 在响应报文中将指定的文件扩展名映射至MIME对应的类型
include /etc/nginx/mime.types;
default_type application/octet-stream; # 除mime.types中的类型外# 指定其它文件的默认MIME类型,浏览器一般会提示下载
types {
text/html html;
image/gif gif;
image/jpeg jpg;
}
示例:
[root@Nginx ~]# vim /usr/local/nginx/html/lee.php
<?php
phpinfo();
?>
[root@Nginx ~]# curl -I 192.168.36.136/lee.php
HTTP/1.1 200 OK
Server: nginx/1.26.1
Content-Type: application/octet-stream
Content-Length: 24
Last-Modified: Fri, 19 Jul 2025 09:38:52 GMT
Connection: keep-alive
ETag: "669a342c-18"
Accept-Ranges: bytes
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
default_type text/html;
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# curl -I 192.168.36.136/lee.php
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Fri, 19 Jul 2025 09:49:49 GMT
Content-Type: text/html
Content-Length: 24
Last-Modified: Fri, 19 Jul 2025 09:38:52 GMT
Connection: keep-alive
ETag: "669a342c-18"
Accept-Ranges: bytes
3.4 核心配置示例
3.4.1 新建一个 PC web 站点
1.添加子配置文件路径(在配置文件的最后面添加此行,不要放在最前面,会导致前面的命令无法
[root@server2 sbin]# vim /usr/local/nginx/conf/nginx.conf
2.创建虚拟主机网站配置
[root@server2 sbin]# mkdir -p /usr/local/nginx/conf.d/
[root@server2 sbin]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@server2 sbin]#
3.重新读取配置文件
[root@server2 sbin]# nginx -s reload
3.添加域名映射
[root@server2 sbin]# vim /etc/hosts
4.测试域名访问效果
[root@server2 ~]# mkdir -p /web/html
[root@server2 ~]# vim /web/html/index.html
web_html
[root@server2 ~]# curl www.timinglee.org
web_html
3.4.2 root与alias
location中使用root指令和alias指令的意义不同
1.root查找路径方式
location /dirtest {root /mnt;}
客户实请求路径:curl www.timinglee.org/dirtest/index.html
Nginx 实际查找的文件路径:/nmt/dirtest/index.html(root路径 + location路径 + 请求资源
)
2.alias查找路径方式
location /alias {alias /mnt/dirtest;}
客户请求路径:curl www.timinglee.org/dirtest/
nginx实际查找文件路径:/nmt/dirtest/index.html(alias路径 + 请求资源
,忽略location
路径)
3.4.3 location的详细使用
- 在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;
- ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配, 而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri
- uri是用户请求的字符串,即域名后面的web文件路径
- 然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。
#语法规则:
location [ = | ~ | ~* | ^~ ] uri { ... }= # 用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求
^~ # 用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头# 对uri的最左边部分做匹配检查,不区分字符大小写
~ # 用于标准uri前,表示包含正则表达式,并且区分大小写
~* # 用于标准uri前,表示包含正则表达式,并且不区分大写
不带符号 #匹配起始于此uri的所有的uri
\ # 用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号#匹配优先级从高到低:
=, ^~, ~/~*, 不带符号
3.4.3.1 匹配案例-精准匹配
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images -p
[root@Nginx ~]# ls /webdata/nginx/timinglee.org/lee/images
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location = /logo.png {root /webdata/nginx/timinglee.org/lee/images;}
}
#上传logo.jpg图片到/webdata/nginx/timinglee.org/lee/images,重启Nginx并访问测试
#访问测试:http://www.timinglee.org/logo.png
3.1.3.2 匹配案例-区分大小写
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~ /logo.PNG {root /webdata/nginx/timinglee.org/lee/images;}
}
#重启Nginx并访问测试
#http://www.timinglee.org/logo.PNG #访问失败,系统中没有logo.PNG文件
3.4.3.3 匹配案例-不区分大小写
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~* /logo.PNG {root /webdata/nginx/timinglee.org/lee/images;}
}
#重启Nginx并访问测试
#http://www.timinglee.org/logo.png
3.4.3.4 匹配案例-URI开始
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images/images{1,2}
[root@Nginx ~]# echo image1 > /webdata/nginx/timinglee.org/lee/images/images1/index.html
[root@Nginx ~]# echo image1 > /webdata/nginx/timinglee.org/lee/images/images2/index.html
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ^~ /images {root /webdata/nginx/timinglee.org/lee/images;index index.html;}location /images1 {root /webdata/nginx/timinglee.org/lee/images;}
}
#重启Nginx并访问测试,实现效果是访问/images1和/images2返回内容一样
[root@node100 ~]# curl 192.168.36.100/images1/
image1
[root@node100 ~]# curl 192.168.36.100/images2/
image1
3.4.3.5 匹配案例-文件名后缀
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/images
#上传一个图片到/webdata/nginx/timinglee.org/lee/images
server {listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js|css)$ {root /webdata/nginx/timinglee.org/lee/images;index index.html;}
}
#重启Nginx并访问测试
192.168.36.200/logo.png
3.4.3.6 匹配案例-优先级
server {
listen 80;server_name lee.timinglee.org;location / {root /webdata/nginx/timinglee.org/lee/html;}location ^~ /images {root /webdata/nginx/timinglee.org/lee/images;index index.html;}location /images1 {root /webdata/nginx/timinglee.org/lee/images;}location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$ {root /data/nginx/static3;index index.html;}
}
#匹配优先级:=, ^~, ~/~*,/
location优先级:(location =) > (location ^~ 路径) > (location ~,~* 正则顺序) >
(location 完整路径) > (location 部分起始路径) > (/)
3.4.3.7 生产使用案例
#直接匹配网站根会加速Nginx访问处理
location = /index.html {......;
}
location / {......;
}#静态资源配置方法1
location ^~ /static/ {......;
}#静态资源配置方法2,应用较多
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {......;
}#多应用配置
location ~* /app1 {......;
}
location ~* /app2 {......;
}
3.4.4 Nginx 账户认证功能
[root@Nginx ~]# htpasswd -cmb /usr/local/nginx/conf/.htpasswd admin lee #-b 表
示非交互建立用户认证
Adding password for user admin
[root@Nginx ~]# htpasswd -mb /usr/local/nginx/conf/.htpasswd lee lee
Adding password for user lee
[root@Nginx ~]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$haGCKgCT$myogggALmqNecTyNupsWQ/
lee:$apr1$H97AyQPF$kGU.Tc4zn1E4Zkp/M4R6G.
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/login
[root@Nginx ~]# echo login > /webdata/nginx/timinglee.org/lee/login/index.html
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name lee.timinglee.org;
location /login {
root /webdata/nginx/timinglee.org/lee;
index index.html;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/conf/.htpasswd";
}
}
#重启Nginx并访问测试
[root@node100 ~]# curl lee.timinglee.org/login/ -u lee:lee
login
[root@node100 ~]# curl lee.timinglee.org/login/ -u admin:lee
login
实验验证:
基于用户的访问
[root@server2 ~]# mkdir -p /web/login/
[root@server2 ~]# touch index.html
[root@server2 ~]# echo "login" > /web/login/index.html
[root@server2 ~]# cat /web/login/index.html
login
[root@server2 ~]#
[root@server2 conf.d]# htpasswd -cm /usr/local/nginx/.htpasswd admin # 创建nginx所需认证文件和用户
# -c创建新的文件会覆盖旧文件
New password:
Re-type new password:
Adding password for user admin
[root@server2 conf.d]# htpasswd -m /usr/local/nginx/.htpasswd lee
New password:
Re-type new password:
Adding password for user lee
[root@server2 conf.d]# cat /usr/local/nginx/.htpasswd
admin:$apr1$.0fUA3Pl$e6CqYByBBLgDfrZAps32y/
lee:$apr1$pPwPp51g$/PBcT9Xl293rX5ciMdaE4.
[root@server2 conf.d]#
[root@server2 conf.d]# vim vhosts.conf
[root@server2 conf.d]# pwd
/usr/local/nginx/conf.d
验证是否成功
[root@server2 ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@server2 ~]# nginx -s reload
[root@server2 ~]# curl www.timinglee.org/login/
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.24.0</center>
</body>
</html>
[root@server2 ~]# curl -uadmin:lee www.timinglee.org/login/
login
[root@server2 ~]#
3.4.5 自定义错误页面和错误日志
自定义错误和日志
[root@server2 web]# mkdir errorpage
[root@server2 web]# echo "错误" > error.html
[root@server2 web]# cat error.html
错误
[root@server2 logs]# touch timinglee.org.err
[root@server2 logs]# touch timinglee.org.acc
[root@server2 logs]# pwd
/usr/local/nginx/logs
[root@server2 logs]#
验证
3.4.7 检测文件是否存在
[root@Nginx ~]# echo "index.html is not exist" >
/webdata/nginx/timinglee.org/lee/error/default.html
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;error_page 404 /40x.html;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;try_files $uri $uri.html $uri/index.html /error/default.html;location = /40x.html {root /webdata/nginx/timinglee/lee/errors;}
}
实验验证:
[root@server2 conf.d]# echo default > /web/errorpage/default.html
[root@server2 conf.d]# cat /web/errorpage/default.html
default
测试
3.4.8 长连接配置
keepalive_timeout timeout [header_timeout]; # 设定保持连接超时时长,0表示禁止长连接,默认为75s# 通常配置在http字段作为站点全局配置
keepalive_requests 数字; # 在一次长连接上所允许请求的资源的最大数量# 默认为100次,建议适当调大,比如:500
示例:
keepalive_requests 3;
keepalive_timeout 65 60;
#开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断
开,第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时
间。
Keep-Alive:timeout=60 #浏览器收到的服务器返回的报文
#如果设置为0表示关闭会话保持功能,将如下显示:
#Connection:close 浏览器收到的服务器返回的报文
#使用命令测试:
[root@node100 ~]# telnet lee.timinglee.org 80
Trying 172.25.254.200...
Connected to lee.timinglee.org.
Escape character is '^]'.
GET / HTTP/1.1 ##输入动作
HOST: lee.timinglee.org ##输入访问HOST
##输入回车
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 20 Jul 2024 12:54:16 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Sat, 20 Jul 2024 08:49:12 GMT
Connection: keep-alive
ETag: "669b7a08-f"
Accept-Ranges: bytes
172.25.254.200
GET / HTTP/1.1 #第二次操作
HOST: lee.timinglee.org #第二次操作
#第二次操作
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sat, 20 Jul 2024 12:54:25 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Sat, 20 Jul 2024 08:49:12 GMT
Connection: close
ETag: "669b7a08-f"
Accept-Ranges: bytes
172.25.254.200
Connection closed by foreign host. #自动断开链接
实验验证
[root@server2 conf]# vim nginx.conf # 长链接位于nginx主配置文件
[root@server2 conf]# pwd
/usr/local/nginx/conf
[root@server2 conf]#
[root@server2 ~]# yum install telnet -y
3.4.9 作为下载服务器配置
autoindex on | off; # 自动文件索引功能,默为off
autoindex_exact_size on | off; # 计算文件确切大小(单位bytes),off 显示大概大小(单位K、M),默认on
autoindex_localtime on | off ; # 显示本机时间而非GMT(格林威治)时间,默认off
autoindex_format html | xml | json | jsonp; # 显示索引的页面文件风格,默认html
limit_rate rate; # 限制响应客户端传输速率(除GET和HEAD以外的所有方法),单位B/s,bytes/second,# 默认值0,表示无限制,此指令由ngx_http_core_module提供
set $limit_rate 4k; # 也可以通变量限速,单位B/s,同时设置,此项优级高.
示例:实现下载站点
#注意:download不需要index.html文件
[root@Nginx ~]# mkdir -p /webdata/nginx/timinglee.org/lee/download
[root@Nginx ~]# cp /root/anaconda-ks.cfg /webdata/nginx/timinglee.org/lee/download
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;try_files $uri $uri.html $uri/index.html /error/default.html;location = /40x.html {root /webdata/nginx/timinglee/lee/errors;}location /download {autoindex on; #自动索引功能autoindex_exact_size on; #计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb、mb、gb)autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间limit_rate 1024k; #限速,默认不限速 }
}
#重启Nginx并访问测试下载页面
实验实现:
1.建立实验素材
2.下载服务器
3.测试
4 nginx高级配置
4.1 nginx状态页
- 基于nginx 模块 ngx_http_stub_status_module 实现,
- 在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
- 否则配置完成之后监测会是提示法错误
#配置示例:
location /nginx_status {
stub_status;
auth_basic "auth login";
auth_basic_user_file /apps/nginx/conf/.htpasswd;
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
# 状态页用于输出nginx的基本状态信息:
# 输出信息示例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106
Active connections: # 当前处于活动状态的客户端连接数# 包括连接等待空闲连接数=reading+writing+waiting
accepts: # 统计总值,Nginx自启动后已经接受的客户端请求连接的总数。
handled: # 统计总值,Nginx自启动后已经处理完成的客户端请求连接总数# 通常等于accepts,除非有因worker_connections限制等被拒绝的连接
requests: # 统计总值,Nginx自启动后客户端发来的总的请求数
Reading: # 当前状态,正在读取客户端请求报文首部的连接的连接数# 数值越大,说明排队现象严重,性能不足
Writing: # 当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting: # 当前状态,正在等待客户端发出请求的空闲连接数开启 keep-alive的情况下,这个值 等于active –(reading+writing)
4.1 nginx压缩功能
#启用或禁用gzip压缩,默认关闭
gzip on | off;#压缩比由低到高从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.0 | 1.1;#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;
gzip_buffers number size;#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
gzip_types mime-type ...;#如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开
gzip_vary on | off;#预压缩,即直接从磁盘找到对应文件的gz后缀的式的压缩文件返回给用户,无需消耗服务器CPU
#注意: 来自于ngx_http_gzip_static_module模块
gzip_static on | off;
示例:
#重启nginx并进行访问测试压缩功能
[root@Nginx ~]# mkdir /webdata/nginx/timinglee.org/lee/data
[root@Nginx ~]# cp /usr/local/nginx/logs/access.log
/webdata/nginx/timinglee.org/lee/data/data.txt
[root@Nginx ~]# echo test > /webdata/nginx/timinglee.org/lee/data/test.html #
小于1k的文件测试是否会压缩
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
@@@@省略内容@@@@
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/css
application/xml text/javascript application/x-httpd-php image/gif image/png;
gzip_vary on;
#重启Nginx并访问测试:
[root@client ~]# curl --head --compressed lee.timinglee.org/data/test.html
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 21 Jul 2024 15:42:46 GMT
Content-Type: text/html
Content-Length: 5
Last-Modified: Sun, 21 Jul 2024 15:40:35 GMT
Connection: keep-alive
ETag: "669d2bf3-5"
Accept-Ranges: bytes
[root@client ~]# curl --head --compressed lee.timinglee.org/data/data.txt
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 21 Jul 2024 15:43:17 GMT
Content-Type: text/plain
Last-Modified: Sun, 21 Jul 2024 15:40:13 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"669d2bdd-3e25b5"
Content-Encoding: gzip
实验验证:
1.准备压缩材料
[root@server2 conf.d]# cp /usr/local/nginx/logs/timinglee.org.acc /web/html/big.html
[root@server2 conf.d]# echo hello > /web/html/small.html
[root@server2 conf.d]# cat /web/html/small.html
hello
2.编辑配置文件
测试压缩效果
[root@server2 conf.d]# cp /usr/local/nginx/logs/timinglee.org.acc /web/html/big.html
[root@server2 conf.d]# curl --head --compressed www.timinglee.org/small.html
4.3 nginx的版本隐藏
[root@Nginx nginx-1.26.1]# vim src/core/nginx.h
#define nginx_version 1026001
#define NGINX_VERSION "1.0"
#define NGINX_VER "HAHA/" NGINX_VERSION
4.4 nginx变量使用
- nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
- 变量可以分为内置变量和自定义变量
- 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
4.4.1 内置变量
官方文档:Alphabetical index of variableshttp://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;
示例:
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;location /var {default_type text/html;echo $remote_addr;echo $args;echo $document_root;echo $document_uri;echo $host;echo $http_user_agent;echo $request_filename;echo $scheme;echo $scheme://$host$document_uri?$args;echo $http_cookie;echo $cookie_key2;echo $http_Accept;}
}[root@client ~]# curl -b "title=lee;key1=lee,key2=timinglee"
"lee.timinglee.org/var?search=lee&&id=666666"
172.25.254.20
search=lee&&id=666666
/webdata/nginx/timinglee.org/lee
/var
lee.timinglee.org
curl/7.29.0
/webdata/nginx/timinglee.org/lee/var
http
http://lee.timinglee.org/var?search=lee&&id=666666
title=lee;key1=lee,key2=timinglee
timinglee
*/*
[root@server2 ~]# rm -rf /usr/local/nginx/
[root@server2 ~]# cd /usr/local/
[root@server2 local]# rm -rf nginx-1.26.3/
[root@server2 ~]# cd /usr/local/
[root@server2 local]# tar zxf /root/nginx-1.26.3.tar.gz
[root@server2 local]# tar zxf /root/echo-nginx-module-0.63.tar.gz
[root@server2 nginx-1.26.3]# ./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=/usr/local/echo-nginx-module-0.63
[root@server2 nginx-1.26.3]# make && make install
验证
[root@server2 conf.d]# nginx -s reload
[root@server2 conf.d]# curl -A "timinglee" -b "lee=a,key1=2" -ulee:lee www.timinglee.org/vars?name=lee
4.4.2 自定义变量
set $name timinglee;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port";
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name lee.timinglee.org;root /webdata/nginx/timinglee.org/lee;location /var {default_type text/html;set $name timinglee;echo $name;set $web_port $server_port;echo $web_port;}
}
测试输出
[root@client ~]# curl lee.timinglee.org/var
timinglee
80
5 Nginx Rewrite 相关功能
- Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
- 此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
- rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
- 比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
- 另外还可以在一定程度上提高网站的安全性。
5.1 ngx_http_rewrite_module 模块指令

5.2 rewrite 案例: break 与 last
rewrite中break与last区别
[root@server2 ~]# mkdir /web/html/{test1,test2,break,last}
[root@server2 ~]# echo test1 > /web/html/test1/index.html
[root@server2 ~]# echo test2 > /web/html/test2/index.html
[root@server2 ~]# echo break > /web/html/break/index.html
[root@server2 ~]# echo last > /web/html/last/index.html
[root@server2 ~]#
测试
5.2.1 rewrite案例: 自动跳转 https
[root@server2 conf.d]# 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
测试
5.2.2 rewrite 案例: 判断文件是否存在
案例:当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
location / {root /data/nginx/html/pc;index index.html;if (!-e $request_filename) {rewrite .* http://www.timinglee.org/index.html; #实现客户端浏览器的302跳转#rewrite .* /index.html; #web服务器内部跳转}
}
#重启Nginx并访问测试
判断文件是否存在
5.3 nginx防盗链
none: # 请求报文首部没有referer首部,# 比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked: # 请求报文有referer首部,但无有效值,比如为空。
server_names: # referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: # 自定义指定字符串,但可使用*作通配符。示例: *.timinglee.org
www.timinglee.*
regular expression: # 被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:
~.*\.timinglee\.com
5.3.1 实现盗链
#新建一个主机172.25.254.20,盗取另一台主机lee.timinglee.org/images/lee.png的图片
[root@client ~]# yum install httpd -y
[root@client html]# vim /var/www/html/index.html
#准备盗链web页面:
<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>
~
#重启apache并访问http://172.25.254.20 测试
#验证两个域名的日志,是否会在被盗连的web站点的日志中出现以下盗链日志信息:
[root@Nginx ~]# cat /usr/local/nginx/logs/access.log
172.25.254.1 - - [22/Jul/2024:09:50:01 +0800] "GET /images/logo.png HTTP/1.1" 304
0 "http://172.25.254.20/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Edg/126.0.0.0"
172.25.254.1 - - [22/Jul/2024:09:50:18 +0800] "GET / HTTP/1.1" 304 0
"http://172.25.254.20/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Edg/126.0.0.0"
5.3.2 实现防盗链

示例:定义防盗链
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {listen 80;server_name www.timinglee.org;root /data/web/html;index index.html;location / {valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;if ($invalid_referer){return 404;}
}location /images {valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;if ($invalid_referer){rewrite ^/ http://www.timinglee.org/daolian.png permanent; #注意此图片不能和正常图片放在一个目录中}}
}
#重启Nginx并访问测试
http://172.25.254.20
6 nginx反向代理功能
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协议转发至指定服务器处理


- 同构代理:用户不需要其他程序的参与,直接通过http协议或者tcp协议访问后端服务器
- 异构代理:用户访问的资源时需要经过处理后才能返回的,比如php,python,等等,这种访问资源需要经过处理才能被访问
6.1 实现http反向代理
官方文档:Module ngx_http_proxy_modulehttps://nginx.org/en/docs/http/ngx_http_proxy_module.html
6.1.1 http 协议反向代理
6.1.1.1 反向代理配置参数
#官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
proxy_pass; # 用来设置将客户端请求转发给的后端服务器的主机# 可以是主机名(将转发至后端服务做为主机头首部)、IP地址:端口的方式# 也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持
#示例:
location /web {index index.html;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
# 内容返回给客户端
} # http://nginx/web/index.html ==> http://1:8080# 重启Nginx测试访问效果:
# curl -L http://www.timinglee.org/web
# 如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri
# 即不能有/ ,用户请求时传递的uri将直接附加至后端服务器之后
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy_pass http://host:port; #proxy_pass后面的url 不能加/
}
...
}
http://HOSTNAME/uri/ --> http://host/uri/
proxy_hide_header field; # 用于nginx作为反向代理的时候
# 在返回给客户端http响应时
# 隐藏后端服务器相应头部的信息
# 可以设置在http,server或location块
# 示例: 隐藏后端服务器ETag首部字段
location /web {index index.html;proxy_pass http://10.0.0.18:8080/;proxy_hide_header ETag;
}
proxy_pass_header field; # 透传
# 默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数
# 如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
# field 首部字段大小不敏感
# 示例:透传后端服务器的Server和Date首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
proxy_pass_request_body on | off;# 是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
# 是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
proxy_set_header;# 可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
#示例:
location ~ /web {proxy_pass http://172.25.254.20:80;proxy_hide_header ETag;proxy_pass_header Server;proxy_pass_request_body on;proxy_pass_request_headers on;proxy_set_header X-Forwarded-For $remote_addr;
}[root@apache20 ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%
{User-Agent}i\"" combined访问后看后端服务器日志proxy_connect_timeout time;
# 配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒用法如下:proxy_connect_timeout 6s;
# 60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码proxy_read_timeout time;
# 配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60sproxy_send_timeout time;
# 配置nginx项后端服务器或服务器组发起write请求后,等待的超时 时间,默认60sproxy_http_version 1.0;
# 用于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0proxy_ignore_client_abort off;
# 当客户端网络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器、
会忽略客户端中断并一直等着代理服务执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求
并立即记录499日志,默认为off。
6.1.1.2 实战案例: 反向代理单台 web 服务器
[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
server {listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}
}
#重启Nginx 并访问测试
6.1.1.3 实战案例: 指定 location 实现反向代理
6.1.1.3.1 针对指定的 location
server {
listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}location ~ /static {proxy_pass http://172.25.254.20:8080;}
}
# 后端web服务器必须要有相对于的访问URL
[root@apache20 ~]# mkdir /var/www/html/static
[root@apache20 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html
[root@apache30 ~]# echo 172.25.254.30 > /var/www/html/index.html
# 重启Nginx并访问测试:
[2025-07-25 17:09.35] ~
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org/static/
static 172.25.254.20
[2025-07-25 17:09.39] ~
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.30
6.1.1.3.2 针对特定的资源实现代理
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
server {listen 80;server_name www.timinglee.org;location / {proxy_pass http://172.25.254.30;}location ~ \.(png|jpg|gif) {proxy_pass http://172.25.254.20:8080;}
}
6.1.1.4 反向代理示例: 缓存功能
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;
# 定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
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];
# 示例:在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache # 定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2 # 定义缓存目录结构层次
# 1:2:2可以生成
2^4x2^8x2^8=2^20=1048576个目录
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方法总是被缓存
6.1.1.4.1 非缓存场景压测
# 准备后端httpd服务器
[root@apache20 app1]# pwd
/var/www/html/static
[root@apache20 static]# cat /var/log/messages > ./log.html # 准备测试页面
[root@apache30 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
Concurrency Level: 100
Time taken for tests: 23.238 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2011251000 bytes
HTML transferred: 2010991000 bytes
Requests per second: 43.03 [#/sec] (mean)
Time per request: 2323.789 [ms] (mean)
Time per request: 23.238 [ms] (mean, across all concurrent requests)
Transfer rate: 84521.97 [Kbytes/sec] received
6.1.1.4.2 准备缓存配置
[root@Nginx ~]# vim /apps/nginx/conf/nginx.conf
@@@@内容省略@@@@
# gzip on;
proxy_cache_path /apps/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m
inactive=120s max_size=1g; #配置在nginx.conf http配置段
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
location ~ /static { # 要缓存的URL 或者放在server配置项对所有URL都进行缓存proxy_pass http://172.25.254.20:8080;proxy_cache proxycache;proxy_cache_key $request_uri;proxy_cache_valid 200 302 301 10m;proxy_cache_valid any 1m; # 必须指定哪些响应码的缓存
}
# /data/nginx/proxycache/ 目录会自动生成
[root@Nginx ~]# ll /apps/nginx/proxy_cache/ -d
drwx------ 3 nginx root 4096 7月 25 20:07 /apps/nginx/proxy_cache/
[root@Nginx ~]# tree /apps/nginx/proxy_cache/
/data/nginx/proxycache/
0 directories, 0 files
6.1.1.4.3 访问并验证缓存文件
#访问web并验证缓存目录
[root@apache30 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
[root@centos8 ~]# ab -n 2000 -c200 http://www.timinglee.org/static/log.html
Concurrency Level: 100
Time taken for tests: 10.535 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2011251000 bytes
HTML transferred: 2010991000 bytes
Requests per second: 94.92 [#/sec] (mean)
Time per request: 1053.507 [ms] (mean)
Time per request: 10.535 [ms] (mean, across all concurrent requests)
Transfer rate: 186435.60 [Kbytes/sec] received# 验证缓存目录结构及文件大小
[root@Nginx ~]# tree /apps/nginx/proxy_cache/
/apps/nginx/proxy_cache/
└── e
└── 50
└── 99
└── 319432ef3663735a9d3cb4e0c1d9950e
3 directories, 0 files
6.1.2 http 反向代理负载均衡

6.1.2.1 http upstream配置参数
# 自定义一组服务器,配置在http块内
upstream name {
server .....
......
}
# 示例
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
server address [parameters];
# 配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
# server支持的parameters如下:
weight=number # 设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number # 给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number # 后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进 行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测fail_timeout=time # 后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup # 设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down # 标记为down状态,可以平滑下线后端服务器resolve # 当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
hash KEY [consistent];
# 基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性
hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致
性hash基于取模运算
hash $request_uri consistent; # 基于用户请求的uri做hash
hash $cookie_sessionid # 基于cookie中的sessionid这个key进行hash调度,实现会话绑定
ip_hash;
# 源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计
算,以实现会话保持
least_conn;
# 最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC
6.1.2.2 反向代理示例: 后端多台 web服务器
172.25.254.10 # Nginx 代理服务器
172.25.254.20 # 后端web A,Apache部署
172.25.254.30 # 后端web B,Apache部署
[root@apache20 ~]# yum install httpd -y
[root@apache20 ~]# echo "web1 172.25.254.20" > /var/www/html/index.html
[root@apache20 ~]# systemctl enable --now httpd
[root@apache30 ~]# yum install httpd -y
[root@apache30 ~]# echo "web2 172.25.254.30" >> /var/www/html/index.html
[root@apache30 ~]# systemctl enable --now httpd# 访问测试
[root@centos8 ~]# curl http://172.25.254.20
web1 172.25.254.20
[root@centos8 ~]# curl http://172.25.254.30
web2 172.25.254.30
[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
upstream webserver {# ip_hash;# hash $request_uri consistent;# hash $cookie_lee# least_conn;server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.30:80 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.10:80 backup;
}
server {listen 80;server_name www.timinglee.org;location ~ / {proxy_pass http://webserver;}
}# 重启Nginx 并访问测试
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.20 web
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.30 web
#关闭172.25.254.20和172.25.254.30,测试nginx backup服务器可用性:
[Administrator.DESKTOP-P19CNDN] ➤ while true;do curl
http://www.timinglee.org;sleep 1;done
[root@Nginx ~]# vim /apps/nginx/conf.d/vhost.conf
http {upstream websrvs {hash $cookie_hello; # hello是cookie的key的名称server 10.0.0.101:80 weight=2;server 10.0.0.102:80 weight-1;}
}[root@centos8 ~]# vim /apps/nginx/conf/conf.d/pc.conf
upstream webserver {# ip_hash;# hash $request_uri consistent;hash $cookie_lee;# least_conn;server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;server 172.25.254.30:80 weight=1 fail_timeout=15s max_fails=3;# server 172.25.254.10:80 backup;
}
server {listen 80;server_name www.timinglee.org;location ~ / {proxy_pass http://webserver;}
}
#测试
[Administrator.DESKTOP-P19CNDN] ➤ curl -b lee=1 www.timinglee.org
6.2 实现 Nginx 四层负载均衡
6.2.1 tcp负载均衡配置参数
stream { # 定义stream相关的服务;
Context:mainupstream backend { # 定义后端服务器hash $remote_addr consistent; # 定义调度算法server backend1.example.com:12345 weight=5; # 定义具体serverserver 127.0.0.1:12345 max_fails=3 fail_timeout=30s;server unix:/tmp/backend3;}upstream dns { # 定义后端服务器server 10.0.0.1:53; #定义具体serverserver dns.example.com:53;}
server { # 定义serverlisten 12345; # 监听IP:PORTproxy_connect_timeout 1s; # 连接超时时间proxy_timeout 3s; # 转发超时时间proxy_pass backend; # 转发到具体服务器组
}
server {listen 127.0.0.1:53 udp reuseport;proxy_timeout 20s;proxy_pass dns;
}
server {listen [::1]:12345;proxy_pass unix:/tmp/stream.socket;}
}
6.2.2 负载均衡实例: MySQL
#在apache20中安装mysql
[root@apache20 ~]# yum install mariadb-server -y
[root@apache20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=20
[root@apache20 ~]# systemctl start mariadb
[root@apache20 ~]# mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.20 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
#在apache30重复以上步骤并在apache20上测试
[root@Nginx ~]# vim /apps/nginx/conf/tcp/tcp.conf
stream {
upstream mysql_server {
server 172.25.254.20:3306 max_fails=3 fail_timeout=30s;
server 172.25.254.30:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.10:3306;
proxy_pass mysql_server;
proxy_connect_timeout 30s;
proxy_timeout 300s;
}
}
# 重启nginx并访问测试:
[root@Nginx ~]# nginx -s reload
# 测试通过nginx负载连接MySQL:
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
# 在10.0.0.28停止MySQL服务
[root@apache20 ~]# systemctl stop mariadb
# 再次测试访问,只会看到mysql-server1.timinglee.org进行响应
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
[root@apache30 ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+
6.2.3 udp 负载均衡实例: DNS
stream {upstream dns_server{server 172.25.254.20:53 max_fails=3 fail_timeout=30s;server 172.25.254.30:53 max_fails=3 fail_timeout=30s;}server {listen 172.25.254.10:53 udp;proxy_pass dns_server;proxy_timeout 1s;proxy_responses 1; # 使用UDP协议时,设置代理服务器响应客户端期望的数据报文数# 该值作为会话的终止条件error_log logs/dns.log;}
}测试:
[root@apache30 named]# dig www.timinglee.org @172.25.254.10
; <<>> DiG 9.16.23 <<>> www.timinglee.org @172.25.254.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33888
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 701447f1bdd8acea0100000066a27b465426b2b4bc7f1dc3 (good)
;; QUESTION SECTION:
;www.timinglee.org. IN A
;; ANSWER SECTION:
www.timinglee.org. 86400 IN A 172.25.254.20
;; Query time: 2 msec
;; SERVER: 172.25.254.10#53(172.25.254.10)
;; WHEN: Fri Jul 26 00:20:22 CST 2024
;; MSG SIZE rcvd: 90
[root@apache30 named]# dig www.timinglee.org @172.25.254.10
; <<>> DiG 9.16.23 <<>> www.timinglee.org @172.25.254.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8932
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 8ecb61bbfe2716df0100000066a27b47a3bb0c3d8e537858 (good)
;; QUESTION SECTION:
;www.timinglee.org. IN A
;; ANSWER SECTION:
www.timinglee.org. 86400 IN A 172.25.254.30
;; Query time: 1 msec
;; SERVER: 172.25.254.10#53(172.25.254.10)
;; WHEN: Fri Jul 26 00:20:23 CST 2024
;; MSG SIZE rcvd: 90
6.3 实现 FastCGI
为什么会有FastCGI?
- FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
- 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server
- 的请求worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
6.3.1 FastCGI配置指令
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 nameNginx默认配置示例:
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
}
6.3.2 FastCGI实战案例 : Nginx与php-fpm在同一服务器
# 利用yum解决php依赖
[root@Nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel oniguruma-devel
# 解压源码并安装
[root@Nginx ~]# ./configure \
--prefix=/usr/local/php \ # 安装路径
--with-config-file-path=/usr/local/php/etc \ # 指定配置路径
--enable-fpm \ # 用cgi方式启动程序
--with-fpm-user=nginx \ # 指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ # 打开curl浏览器支持
--with-iconv \ # 启用iconv函数,转换字符编码
--with-mhash \ # mhash加密方式扩展库
--with-zlib \ # 支持zlib库,用于压缩http压缩传输
--with-openssl \ # 支持ssl加密
--enable-mysqlnd \ # mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ # 关闭debug功能
--enable-sockets \ # 支持套接字访问
--enable-soap \ # 支持soap扩展协议
--enable-xml \ # 支持xml
--enable-ftp \ # 支持ftp
--enable-gd \ # 支持gd库
--enable-exif \ # 支持图片元数据
--enable-mbstring \ # 支持多字节字符串
--enable-bcmath \ # 打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd # 支持systemctl 管理cgi
[root@Nginx ~]# cd /usr/local/php/etc
[root@Nginx etc]# cp php-fpm.conf.default php-fpm.conf
[root@Nginx etc]# vim php-fpm.conf
去掉注释
pid = run/php-fpm.pid # 指定pid文件存放位置
[root@Nginx etc]# cd php-fpm.d/
[root@Nginx php-fpm.d]# cp www.conf.default www.conf
# 生成主配置文件
[root@Nginx php-fpm.d]# cd /root/php-8.3.9/
[root@Nginx php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@Nginx ~]# vim /usr/local/php/etc/php.ini
[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
date.timezone = Asia/Shanghai # 修改时区
# 生成启动文件
[root@Nginx ~]# cd /root/php-8.3.9/
[root@Nginx php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by
this unit.
# ProtectSystem=full # 注释该内容
[root@Nginx php-8.3.9]# systemctl start php-fpm.service
[root@Nginx php-8.3.9]# netstat -antlupe | grep php
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 0
820758 176202/php-fpm: mas
[root@Nginx ~]# mkdir /data/php -p
[root@centos8 ~]# cat /data/php/index.php # php测试页面
<?php
phpinfo();
?>
[root@Nginx ~]# vim /apps/nginx/conf.d/php.conf
server {listen 80;server_name php.timinglee.org;root /data/php;location ~ \.php$ {fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;include fastcgi.conf;}
}
# 重启Nginx并访问web测试
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# vim .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin:/apps/nginx/sbin:/usr/local/php/bin
export PATH
[root@Nginx ~]# source .bash_profile
6.3.3 php的动态扩展模块(php的缓存模块)

[root@Nginx ~]# tar zxf memcache-8.2.tgz
[root@Nginx ~]# cd memcache-8.2/
[root@Nginx memcache-8.2]# yum install autoconf
[root@Nginx memcache-8.2]# phpize
[root@Nginx memcache-8.2]# ./configure && make && make install
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-nonzts-20230831/
[root@Nginx memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-
20230831/
memcache.so opcache.so
[root@Nginx ~]# cd memcache-8.2/
[root@Nginx memcache-8.2]# ls
autom4te.cache config.log configure.ac example.php Makefile.fragments
README
build config.m4 config.w32 include Makefile.objects runtests.php
config9.m4 config.nice CREDITS libtool memcache.la src
config.h config.status docker LICENSE memcache.php
tests
config.h.in configure Dockerfile Makefile modules
[root@Nginx memcache-8.2]# cp example.php memcache.php /data/php/
[root@Nginx ~]# vim /data/php/memcache.php
define('ADMIN_USERNAME','admin'); // Admin Username
define('ADMIN_PASSWORD','lee'); // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
$MEMCACHE_SERVERS[] = 'localhost:11211'; // add more as an array
#$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
[root@Nginx ~]# vim /usr/local/php/etc/php.ini
;extension=zip
extension=memcache
;zend_extension=opcache
[root@Nginx ~]# systemctl reload php-fpm
[root@Nginx no-debug-non-zts-20230831]# php -m | grep mem
memcache
[root@Nginx ~]# yum install memcached -y
[root@Nginx ~]# systemctl enable --now memcached.service
[root@Nginx ~]# netstat -antlupe | grep memcache
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN
976 1037243 186762/memcached
[root@Nginx ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"
访问 http://php.timinglee.org/example.php 不断刷新
访问 http://php.timinglee.org/memcache.php 查看命中效果
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/index.php
@@@内容忽略@@@
Concurrency Level: 10
Time taken for tests: 0.514 seconds
Complete requests: 500
Failed requests: 44
(Connect: 0, Receive: 0, Length: 44, Exceptions: 0)
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/example.php
@@@内容忽略@@@
Concurrency Level: 10
Time taken for tests: 0.452 seconds
Complete requests: 500
Failed requests: 0
6.3.4 php高速缓存
[root@Nginx ~]# rm -fr /apps/nginx/
[root@Nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@Nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@Nginx ~]# cd nginx-1.26.1/
[root@Nginx nginx-1.26.1]# ./configure --prefix=/apps/nginx --user=nginx --
group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_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
[root@Nginx nginx-1.26.1]# make && make install
[root@Nginx ~]# vim /apps/nginx/conf.d/php.conf
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name php.timinglee.org;
root /data/php;
location /memc {
internal;
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;
include fastcgi.conf;
}
}
[root@Nginx ~]# systemctl start nginx.service
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/index.php
Concurrency Level: 10
Time taken for tests: 0.255 seconds
Complete requests: 500
Failed requests: 0
7 nginx 二次开发版本
7.1 openresty
7.2 编译安装 openresty
[root@Nginx ~]#dnf -yq install gcc pcre-devel openssl-devel perl
[root@Nginx ~]#useradd -r -s /sbin/nologin nginx
[root@Nginx ~]#cd /usr/local/src
[root@Nginx src]#wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@Nginx src]#tar xf openresty-1.17.8.2.tar.gz
[root@Nginx src]#cd openresty-1.17.8.2/
[root@Nginx openresty-1.17.8.2]#./configure \
--prefix=/apps/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
--with-pcre --with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
[root@Nginx openresty-1.17.8.2]#make && make install
[root@Nginx openresty-1.17.8.2]#ln -s /apps/openresty/bin/* /usr/bin/
[root@Nginx openresty-1.17.8.2]#openresty -v
nginx version: openresty/1.17.8.2
[root@Nginx openresty-1.17.8.2]#openresty
[root@Nginx openresty-1.17.8.2]#ps -ef |grep nginx
[root@Nginx ~]#curl 10.0.0.18