一.Web 服务基础介绍
正常情况下的单次web服务访问流程:
1.1apache
1.11Apache prefork 模型
预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
每个子进程有一个独立的线程响应用户请求
相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.1.2 Apache worker 模型
一种多进程和多线程混合的模型
有一个控制进程,启动多个子进程
每个子进程里面包含固定的线程
使用线程程来处理请求
当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,
由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
1.1.3 Apache event模型
Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)
每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
1.2Nginx-高性能的 Web 服务端
1.2.1服务端 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.2.2 磁盘 I/O
磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相 应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存, 如果是比较大的数据也需要等待时间
机械磁盘的寻道时间、旋转延迟和数据传输时间: 寻道时间:是指磁头移动到正确的磁道上所花费的时间,寻道时间越短则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.17ms 10000转的机械盘平均延迟:60*1000/10000/2 = 3ms 15000转的机械盘平均延迟:60*1000/15000/2 = 2ms
每秒最大IOPS的计算方法: 7200转的磁盘IOPS计算方式:1000毫秒/(9毫秒的寻道时间+4.17毫秒的平均旋转延迟时 间)=1000/13.13=75.9 IOPS 10000转的磁盘的IOPS计算方式:1000毫秒/(6毫秒的寻道时间+3毫秒的平均旋转延迟时 间)=1000/9=111IOPS 15000转的磁盘的IOPS计算方式:15000毫秒/(4毫秒的寻道时间+2毫秒的平均旋转延迟时 间)=1000/6=166.6 IOPS
1.2.3 网络 I/O
网络通信就是网络协议栈到用户空间进程的IO就是网络IO
网络I/O 处理过程
获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)
不论磁盘和网络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 模型
阻塞型、非阻塞型、复用型、信号驱动型、异步
阻塞型 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是否完成,这种 方式简单,但是比较慢,用的比较少。
非阻塞型 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时间,实 际使用很少
多路复用 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复用
信号驱动式 I/O 模型 (signal-driven IO)
信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知 进程。
调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主 程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO信 号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进 程所需要的数据从内核空间拷贝到用户空间
此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处 理函数的通知。
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续 运行并不阻塞
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续 运行并不阻塞
当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。
优 点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此 可以提高资源的利用率
缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程 请求后
进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。
异步 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.3.3 五种 IO 对比
1.3.4Nginx 事件驱动模型
模型 | 适用系统 | 特点 | 备注 |
---|---|---|---|
select | Linux / Windows | 早期模型,最大 1024 文件描述符 | 通用,但性能受限 |
poll | Linux | 升级版 select,取消 1024 限制 | 需编译 --with-poll_module |
epoll | Linux 2.6+ | 事件通知机制,仅处理活跃 fd,性能高 | 生产环境首选 |
kqueue | FreeBSD / OpenBSD / NetBSD / macOS | 类似 epoll,BSD 专用 | 性能优异 |
IOCP | Windows | 异步 I/O,支持高并发 | Windows 平台首选 |
rtsig | Linux | 实时信号驱动,队列 1024 | 老旧,极少使用 |
/dev/poll | Solaris / HP-UX | 设备文件方式 | Solaris 平台专用 |
eventport | Solaris 10+ | 防止内核崩溃,Solaris 10+ 推荐 | 取代 /de |
1.4 零拷贝
1. 4.1原理
零拷贝 = 让数据 “内核 ↔ 网卡” 直接搬运,不再经过“用户空间”,省掉 2 次 CPU 复制 + 2 次上下文切换。
1.4.2 三种经典零拷贝实现
场景 | 系统调用 | 拷贝次数 | 上下文切换 | 适用 |
---|---|---|---|---|
传统 read+write | read → write | 4 次 | 4 次 | 通用 |
mmap+write | mmap → write | 3 次 | 4 次 | 小文件 |
sendfile | sendfile | 2 次 | 2 次 | 大文件、静态资源 |
sendfile + DMA scatter-gather | sendfile + SG-DMA | 0 次 | 2 次 | 支持 SG-DMA 的网卡 |
1.4.3 Nginx 配置一步到位
http {
sendfile on; # 开启 sendfile 零拷贝
tcp_nopush on; # 与 sendfile 配合,减少小包
tcp_nodelay off; # 大文件场景可关闭 nodelay
}
sendfile on
默认已启用,只需确认没有被off
覆盖。
1.4.4 性能对比实验(1 GB 文件)
模式 | 吞吐量 | CPU 占用 |
---|---|---|
传统 | 400 MB/s | 85 % |
sendfile | 1.2 GB/s | 10 % |
1.4.5一句话命令验证
# 查看 Nginx 是否在用零拷贝
strace -c -e trace=sendfile nginx 2>&1 | grep sendfile
# 出现大量 sendfile 调用即成功
1.4.6 扩展:DMA + SG-DMA(Linux 4.5+)
DMA SG-DMA(scatter-gather)让网卡直接从页缓存 DMA,CPU 0 拷贝。
需硬件 + 内核支持,Nginx 已透明使用,无需额外配置。
1.4.7一句话总结
Nginx 零拷贝 = sendfile on
+ 支持 SG-DMA 的网卡,让 1 GB 文件传输 CPU 占用从 85 % 降到 10 %,复制即用。
二.Nginx 安装
2.4.1 Nginx版本和安装方式
Nginx版本
Mainline version 主要开发版本,一般为奇数版本号,比如1.19
Stable version 当前最新稳定版,一般为偶数版本,如:1.20
Legacy versions 旧的稳定版,一般为偶数版本,如:1.18
Nginx安装可以使用yum或源码安装,但是推荐使用源码编译安装
yum的版本比较旧
编译安装可以更方便自定义相关路径
使用源码编译可以自定义相关功能,更方便业务的上的使用
编译安装 Nginx
官方源码包下载地址:
这里我们以nginx-1.24为例
https://nginx.org/download/nginx-1.24.0.tar.gz
wget https://nginx.org/download/nginx-1.24.0.tar.gz
dnf install gcc pcre-devel zlib-devel openssl-devel -y
useradd -s /sbin/nologin -M nginx
tar zxf nginx-1.24.0.tar.gz
useradd -s /sbin/nologin -M nginx
cd nginx-1.24.0/
make && make install
nginx完成安装以后,有四个主要的目录
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin src
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二进制启动脚本,可以接受不同的参数以实现不同的功能。
验证版本及编译参数
[root@Nginx ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@Nginx ~]# source ~/.bash_profile
[root@Nginx ~]# nginx -V
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 --with http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --
with-stream_realip_module
关闭火墙(火墙放行)
firewall-cmd --permanent ---add-service=http
—— 在火墙中放行http服务
firewall-cmd --reload
—— 重启火墙
进入nginx默认共享目录
会将该目录的东西都共享到网络上
共享目录里的index.html
进入该目录后,ls查看一下该目录的东西
可以看到一个叫index.html的东西,这是它的默认发布文件,里边就能够访问用户指定的内容了
这里我用echo写了个ip地址进去,访问即可看到,你们可以自己随便写点东西,如用户名,命令如下:
echo lincoln > index.html
查看默认使用的端口
默认端口为80
netstat -antlupe | grep nginx
实例:
修改默认使用的端口
先进入/etc/nginx/路径,在里边查看一下文件(如下图)
可以看到一个nginx.conf的文件,修改此文件里边的参数即可改变端口号
进入nginx.conf
vim nginx.conf
再nginx -s reload生效
nginx默认配置目录
2.4.2改变nginx默认共享目录的发布文件
1、创建一个自己的文件(这里是test.html)
确保自己在/usr/share/nginx/html/路径下:
cd /usr/share/nginx/html/
在此路径下创建一个自己的文件,这里为test.html
vim test.html
示例
在里边随便编写一些字符,这里博主写的是自己的用户名
wq保存退出
2、将test.html更改为默认发布文件
进入路径/etc/nginx/并进入nginx.conf
cd /etc/nginx/
vim nginx.conf
示例
找到此行,添加如图指令
Tips:index可以指定多个文件,但是不会全部一起出现,而是会排队访问
修改完后,重启nginx
nginx -s reload
此时,我们在去浏览器访问自己虚拟机的ip地址,可以发现已经是test.html这个文件的内容了
2.4.3改变nginx默认共享目录的路径
1、大致思路(与第五大点类似)
与修改默认发布文件(第五大点)相似,这里就不再赘述,基本思路就是:
(1)自己在/usr/share/nginx/下,新建一个目录
(2)随后在自己建的新目录下建立一个文件(如index.html)
(3)还是进入路径/etc/nginx/并进入nginx.conf
(4)修改此行的路径,将其修改成自己创的那个目录(如图)
注意:修改了默认路径后,下一行的index出也需要修改成自己目录里有的文件哦!此处跟着做的话就是index.html
(5) 修改完后,重启nginx
2.4.4 nginx访问控制
默认任何人都能访问你的nginx目录,如何限制呢?location能够解决
1、基于ip的访问控制「步骤」
(1)进入nginx.conf
vim /etc/nginx/nginx.conf
示例
(2)进入后添加location
进入后:找到server项里,这点很重要!!!
注意:location 大括号下的指令有读取顺序,前面的会先读取执行,然后再是后面的,比如这里先把deny all先写在前面,allow写在后面,就会先执行deny命令,而后面的allow就不会生效了
(3) 修改完,重启nginx
nginx -s reload
这样访问控制就设置成功了,现在只有允许的ip能够访问此目录,其他ip访问会出现网页报错(如图):
2、 基于用户的访问控制「步骤」
(1)先安装软件包httpd-tools
dnf install httpd-tools -y
示例
(2) 使用htpasswd
我们先查看一下/etc/nginx/.htpasswd:
ll /etc/nginx/.htpasswd
下面分两种情况:
1)显示“无法访问...没有那个文件或目录”
第一次使用htpassd应该都是这种情况,这是我们使用-cm:
htpasswd -cm /etc/nginx/.htpasswd test(这里的test是一个用户!)
按enter后输入密码,之后就会显示这个,代表该用户已经有密码了
2)显示出了文件
这种情况代表已经有了该文件,所以把-cm的c去掉,代表不创建、仅修改,这样就不会覆盖其他用户
htpasswd -m /etc/nginx/.htpasswd test(这里的test是一个用户!)
(3)进入nginx.conf
vim /etc/nginx/nginx.conf
示例
(4) 进入后,添加location
图中location下的名词解释:
auth basic on; —— 代表开启基本认证
auth basic user file /etc/nginx/.htpasswd; —— 代表指定认证文件
(5) 修改完,重启nginx
nginx -s reload
此时访问就会被要求输入用户和密码,这样用户访问控制就完成了
2.4.5 平滑升级版本和回滚版本
将旧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
[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]# kill -USR2 48732 #nginx worker ID
#USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的
nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进
程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
[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
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]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0 ##依旧是旧版本生生效
Date: Thu, 18 Jul 2024 07:45:58 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2024 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes
#回收旧版本
[root@Nginx sbin]# kill -WINCH 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 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 2024 07:59:45 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2024 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
[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 2024 08:31:51 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 18 Jul 2024 03:41:13 GMT
Connection: keep-alive
ETag: "66988ed9-267"
Accept-Ranges: bytes
这里不要make install 因为已经有nginx了,并且此时已经在对外服务了平滑升版本
杀死之前的nginx占用
确保成功开启
三 nginx虚拟机
3.1 基于ip的虚拟机
(1)添加了2个ip地址)
将新的ip分配不同的站点
我们需要做到访问10ip时去看一个文件,访问20ip时去看另一个文件,这样就分配了不同的站点
( 1)新建一个指定目录
建立一个指定目录,并在其下再建立news和bbs两个文件
mkdir /usr/share/nginx/virtualhost/{news,bbs} -p
(2)指定ip地址访问文件
将10ip指定访问news的index.html;20ip指定访问bbs的index.html
echo 192.168.76.10 > /usr/share/nginx/virtualhost/news/index.html
示例
(3)进入 /etc/nginx/conf.d/
cd /etc/nginx/conf.d/
(4) 创建进入vhosts.conf
vim vhosts.conf
示例
(5)添加指令
添加下图指令 ,一个server就是一个虚拟主机
(6)修改完,重启nginx
nginx -s reload
这样我们浏览器访问10ip就会显示10的ip地址, 访问20ip就会显示20的ip地址,这样就做到了不同ip分配不同站点
3.2 基于域名的虚拟机
基于域名的虚拟机建立在基于ip之上,所以前期操作都是相同的,不再赘述,这里就讲不同的地方
3.2.1进入vhosts.conf,修改listen添加server_name
1)修改listen
将listen修改成80端口号
2)添加server_name
添加server_name,并给予网站域名
3.2.1添加dns
写了域名但是系统并不知道,所以要配置dns来让系统知道一个ip对应一个域名,这里演示配置Linux的dns,所以应该后面测试应该用Linux的浏览器访问域名哦!
(1)进入/etc/hosts
vim /etc/hosts
示例
(2)添加dns
(3)测试
这里演示配置Linux的dns,所以应该后面测试应该用Linux的浏览器访问域名哦!
news.lincoln.org对应10ip
bbs.lincoln.org对应20ip
4 Nginx核心配置
Main 全局配置段常见的配置指令分类
正常运行必备的配置
优化性能相关的配置
用于调试及定位问题相关的配置
事件驱动相关的配置
全局配置说明:
#========== 全局段 ==========
user nginx nginx; # 运行用户与组
worker_processes auto; # 与 CPU 核心数一致
worker_cpu_affinity auto; # 自动绑定物理核心
worker_rlimit_nofile 65536; # 所有 worker 最大文件句柄
pid /usr/local/nginx/logs/nginx.pid;
error_log /usr/local/nginx/logs/error.log crit;# CPU 绑定示例(如需手动绑定,请取消注释并按需修改)
#worker_cpu_affinity 0001 0010 0100 1000; # 0-3 号 CPU
#worker_cpu_affinity 0101 1010; # 0,2,1,3 号 CPU
#worker_cpu_affinity 00000010 00001000 00100000 10000000; # 1,3,5,7 号 CPU#将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进 程独占以一核心CPU,但是可以保证此进程不运行在其他核心上,这就极大减少了nginx的工作进程在不同的 cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务 器的性能。
CPU MASK:
00000001:0号CPU
00000010:1号CPU
10000000:7号CPU
#========== events ==========
events {
use epoll; # 高性能事件驱动
worker_connections 65535; # 单进程最大并发
accept_mutex on; # 防止惊群
multi_accept on; # 一次接收多个连接
}
4.1 实现nginx高并发
[root@Nginx ~]# ulimit -n 102400
[root@Nginx ~]# ab -c 5000 -n 10000 http://10.0.0.8/
#默认配置不支持高并发,会出现以下错误日志
[root@Nginx ~]# tail /apps/nginx/logs/error.log
2020/09/24 21:19:33 [crit] 41006#0: *1105860 open() "/apps/nginx/html/50x.html"
failed (24: Too many open files), client: 10.0.0.7, server: localhost, request:
"GET / HTTP/1.0", host: "10.0.0.8"
2020/09/24 21:19:33 [crit] 41006#0: accept4() failed (24: Too many open files)
2020/09/24 21:19:33 [crit] 41006#0: *1114177 open()
"/apps/nginx/html/index.html" failed (24: Too many open files), client: 10.0.0.7,
server: localhost, request: "GET / HTTP/1.0", host: "10.0.0.8"
#修改配置
[root@Nginx ~]# vim /etc/security/limits.conf
* - nproc 100000
[root@Nginx ~]# vim /apps/nginx/conf/nginx.conf
worker_rlimit_nofile 100000;
[root@Nginx ~]# systemctl restart nginx
但是也有缺点,如果没有绑定,一个进程可能会占用多个核,造成浪费,最好将它们绑定在一起
这里一个master下开6个work,并不是越多越好
压力测试没过,拉爆了服务器
日志
事件驱动模型 能驱动100000链接数
设定参数,每一个work能打开的文件数量有多少
虽然设定好了环境,还是不能承载住100000的压力
系统里能打开的文件个数只有1024,是扛不住100000的并发量
修改文件
文件虽然改了,但是默认不生效,直接指定100000就行
现在就可以通过压力测试了
-n请求总量 -c并发量 总共100000个请求,每次发送5000个并发
4.2防止惊群(新请求会同时唤起所有worker)
那以上都是对于全局配置的实验测试
还是刚刚那个配置文件
写一个php来动态测试
改之前,是兼容模式
改之后,让我们的浏览器能够识别过来的请求是是什么类型,这样方便浏览器去修饰
编辑日志类型
长连接时间不能超过65秒
子配置文件
位置别放错,不然会被覆盖,放到默认server的后面,要保留默认的内容,不然无法区分
新建子配置文件路径并编辑子配置文件
最简单的虚拟主机
端口 listen 80;
基于域名,IP不用写 server_name
默认发布目录 root
默认发布文件 index
测试:
域名要解析 在/etc/hosts中
访问的不是域名,就是输出默认的server,但是访问的是域名,输出的就是我们编辑的内容
记得编辑完后要重启nginx
nginx -t
nginx -s reload
4.3 root 与 alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location
root示例:
server {
listen 80;
server_name lee.timinglee.org;
location / {
root /webdata/nginx/timinglee.org/lee/html;
}
location /dirtest {
root /mnt;
}
#必须建立/mnt/dirtest才能访问
}
[root@Nginx ~]# mkdir /mnt/dirtest/
[root@Nginx ~]# echo dirtest page > /mnt/dirtest/index.html
[root@Nginx ~]# nginx -s reload
#重启Nginx并访问测试
[root@node100 ~]# curl lee.timinglee.org/dirtest/
dirtest page
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于 location上下文,此指令使用较少
alias示例:
server {
listen 80;
server_name lee.timinglee.org;
location / {
root /webdata/nginx/timinglee.org/lee/html;
}
location /dirtest {
root /mnt;
}
location /alias { #注意about后不要加/
#使用alias的时候uri后面如果加了斜杠,则下面的路径配置
必须加斜杠,否则403
alias /mnt/dirtest; #当访问alias的时候,会显示alias定义的/mnt/dirtest
里面的内容
}
}
#重启Nginx并访问测试
[root@node100 ~]# curl lee.timinglee.org/alias/
dirtest page
4.4 优先级
在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;
ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,
而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最 高的一个uri
uri是用户请求的字符串,即域名后面的web文件路径
然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理 此请求
对目录匹配 (~* = ~) > 不带符号 > ^~ >= #=不能指定目录所以排在最后
对文件匹配 = > (* = ~) >不带符号 > ^~
[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
[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 172.25.254.200/images1/
image1
[root@node100 ~]# curl 172.25.254.200/images2/
image1
[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并访问测试
172.25.254.200/logo.png
4.5自定义错误页
自定义错误页,同时也可以用指定的响应状态码进行响应, 可用位置:http, server, location, if in location
error_page code ... [=[response]] uri;
示例:
listen 80;
server_name www.timinglee.org;
error_page 500 502 503 504 /error.html;
location = /error.html {
root /data/nginx/html;
}
#重启nginx并访问不存在的页面进行测试
示例:自定义错误页面
[root@Nginx ~]# mkdir /webdata/nginx/timinglee/lee/errors -p
[root@Nginx ~]# echo error page > /webdata/nginx/timinglee/lee/errors/40x.html
server {
listen 80;
server_name lee.timinglee.org;
error_page 404 /40x.html
location = /40x.html {
root /webdata/nginx/timinglee/lee/errors;
}
}
测试:
[root@node100 ~]# curl lee.timinglee.org/haha
error page
4.6 自定义错误日志
可以自定义错误日志
Syntax: error_log file [level];
Default:
error_log logs/error.log error;
Context: main, http, mail, stream, server, location
level: debug, info, notice, warn, error, crit, alert, emerg
示例:
[root@Nginx ~]# mkdir "/var/log/nginx" -p
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name lee.timinglee.org;
error_page 404 /40x.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location = /40x.html {
root /webdata/nginx/timinglee/lee/errors;
}
}
#重启nginx并访问不存在的页面进行测试并验证是在指定目录生成新的日志文件
4.7检测文件是否存在
try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如 果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一 个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内 部500错误。
语法格式
Syntax: try_files file ... uri;
try_files file ... =code;
Default: —
Context: server, location
示例: 如果不存在页面, 就转到default.html页面
[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;
}
}
测试:
curl lee.timinglee.org
4.8 Nginx 账户认证功能
由 ngx_http_auth_basic_module 模块提供此功能
示例:
[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
当认证文件不存在是需要用-c建立,当认证文件存在时如果加-c参数会覆盖原文件内容
指定你的用户文件
4.9 长连接配置
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.
#自动断开链接
这里全程都不会断,直到时间超时,才会断
超时之后再访问,又要做一次TCP的三次握手
这里不回车,不会建立长连接,也就不会超时
设置长连接的次数,最多只能发送3次
实际设置是65秒,但是用户看到的是60秒
4.10 nginx作为下载服务器
创建存放共享资源的目录
参数介绍:
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, 表示无限制 , 此指令由
示例:实现下载站点
#注意: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;
示GMT时间
}
limit_rate 1024k;
#on表示显示本机时间而非GMT(格林威治)时间,默为为off显
#限速,默认不限速 }
#重启Nginx并访问测试下载页面
编写测试资源
配置文件
这里显示的的是server的时间
这里是把时间变成了 localtime时间
这里是显示这个资源的大小
这里是改变资源大小的显示形式
输入www.timinglee.org/download进去下载页
这里设置下载速度
重新下载的资源大小变了
4.11 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:
accepts:
handled:
连接
requests:
#当前处于活动状态的客户端连接数
#包括连接等待空闲连接数=reading+writing+waiting
#统计总值,Nginx自启动后已经接受的客户端请求连接的总数。
#统计总值,Nginx自启动后已经处理完成的客户端请求连接总数
#通常等于accepts,除非有因worker_connections限制等被拒绝的
#统计总值,Nginx自启动后客户端发来的总的请求数
Reading:
Writing:
访问量很大
Waiting:
#当前状态,正在读取客户端请求报文首部的连接的连接数
#数值越大,说明排队现象严重,性能不足
#当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明
#当前状态,正在等待客户端发出请求的空闲连接数
开启 keep-alive的情况下,这个值等于active –
(reading+writing)
单纯配置参数所有人都可以看到请求信息
状态页
有效的链接,当前处于活跃的链接数
从重启之后接收到的请求连接的总数 accepts
加上认证之后,就需要登录,才能看到状态页了
4.12 Nginx 压缩功能
Nginx支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文 件大小将比源文件显著变小,样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相 应的CPU资源。
Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module,默认是内置模块
配置指令如下:
参数介绍:
# 启用或禁用 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
测试:
分别生成两个文件,一个小于1K,一个大于1K
配置nginx主配置文件
查看响应报文头部,可以看出超过1k的文件显示压缩:在传输过程中被压缩,原文件不变
文件太多,不好确认,用命令来只看首部并且查看是否压缩
curl --head --compressed 172.25.254.10/big.html
这里small没有超过4k所以他不会被压缩,big超过了4k所以被压缩了
4.13 Nginx的版本隐藏
用户在访问nginx的时候,我们可以从报文中获得nginx的版本,相对于裸漏版本号的nginx,我们把其隐 藏起来更安全
[root@Nginx nginx-1.26.1]# vim src/core/nginx.h
#define nginx_version
#define NGINX_VERSION
#define NGINX_VER
1026001
"1.0"
"HAHA/" NGINX_VERSION
4.14 Nginx 变量使用
$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
*/*
先要做好环境
把之前配置好的子文件备份,等下可以直接用
关闭服务方便操作
删除之前nginx目录
删除之前的版本目录
重新解压之前的安装包,并且解压插件
重新安装并且一定要加上新的插件
然后make&make install就行
然后把之前备份的配置文档还原回去
尝试重新启动,启动成功,环境就配置好了
这里实验是发生了错误
是因为刚刚删除nginx时,之前关于子配置文件的include也被删除了,所以没检测到
虽然重新安装了nginx,之前写的环境配置,也要尽力还原,不然影响实验
systemctl restart nginx.service
错误情况:
PID 文件未生成或丢失
重新启动 Nginx 以生成 PID 文件
4.15 自定义变量
假如需要自定义变量名称和值,使用指令set $variable value;
语法格式:
Syntax: set $variable value;
Default: —
Context: server, location, if
示例:
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.rewrite 指令
5.1 域名永久与临时重定向
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理
官方文档: https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
语法格式 : rewrite regex replacement [flag];
rewrite将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI
注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成 后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的 标志位用于控制此循环机制
如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301
检查一下nginx里加载了参数没有,加载了才可以使用
if指令
如果是一个lee浏览器就显示lee
如果是timinglee浏览器就显示timinglee
测试:
set指令
自己设定了一个变量name
break指令
return指令
[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 / {
rewrite / http://lee.timinglee.com redirect;
#rewrite / http://lee.timinglee.com permanent;
}
}
server {
listen 80;
server_name lee.timinglee.com;
root /webdata/nginx/timinglee.com/lee;
}
测试:
默认不能显示重启后的页面,要访问得加上-L
永久301,临时302
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301
5.2 rewrite 案例: break 与 last
测试: 访问break请求被rewrite至test1,而访问test1转递请求再次被rewrite发送至test2,此测试last和break 分别有什么区别
break:用于中断当前相同作用域(location)中的其他 Nginx 配置 与该指令处于同一作用域的Nginx 配置中,位于它前面的配置生效 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行 Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server 块和 locationif 块中使用。
break和last区别案例:
[root@nginx]# mkdir /data/web/html/{test1,test2,break,last}
[root@nginx]# echo test1 > /data/web/html/test1/index.html
[root@nginx]# echo test2 > /data/web/html/test2/index.html
[root@nginx]# echo last > /data/web/html/last/index.html
[root@nginx]# echo break > /data/web/html/break/index.html
[root@nginx nginx]# vim conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
location /break {
root /data/web/html;
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1 ;
}
location /last {
root /data/web/html;
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1 ;
}
location /test1 {
default_type text/html;
return 666 "new test1";
}
location /test2 {
root /data/web/html;
}
}
#测试:
[root@client ~]# curl -L www.timinglee.org/break/index.html
test1
[root@client ~]# curl -L www.timinglee.org/last/index.html
new test1[root@client ~]#
修改文件
做重定向后
访问break时候重定向到test1,test1又重定向到lee页面
5.3 rewrite案例: 自动跳转 https
案例:基于通信安全考虑公司网站要求全站 https,因此要求将在不影响用户请求的情况下将http请求全 部自动跳转至 https,另外也可以实现部分 location 跳转
[root@centos8 ~]#vim /apps/nginx/conf.d/pc.conf
server {
listen 443 ssl;
listen 80;
ssl_certificate /apps/nginx/certs/www.timinglee.org.crt;
ssl_certificate_key /apps/nginx/certs/www.timinglee.org.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
server_name www.timniglee.org;
location / {
#针对全站跳转
root /data/nginx/html/pc;
index index.html;
if ($scheme = http ){
#如果没有加条件判断,会导致死循环
rewrite / https://$host redirect;
}
}
}
}
location /login {
if ($scheme = http ){
}
#重启Nginx并访问测试
[root@centos7 ~]#curl -ikL www.timinglee.org
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.18.0
Date: Thu, 08 Oct 2020 15:23:48 GMT
Content-Type: text/html
Content-Length: 145
#针对特定的URL进行跳转https
#如果没有加条件判断,会导致死循环
rewrite / https://$host/login redirect;
Connection: keep-alive
Location: https://www.timinglee.org
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 08 Oct 2020 15:23:48 GMT
Content-Type: text/html
Content-Length: 7
Last-Modified: Sat, 26 Sep 2020 01:18:32 GMT
Connection: keep-alive
ETag: "5f6e96e8-7"
Accept-Ranges: bytes
pc web
做全站加密
这里没写好,子目录也能访问到网址了
5.4 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.4 Nginx 防盗链
防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标 记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗 链,referer就是之前的那个网站域名,正常的referer信息有以下几种
none:
blocked:
server_names:
#请求报文首部没有referer首部,
#比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
#请求报文有referer首部,但无有效值,比如为空。
#referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: #自定义指定字符串,但可使用*作通配符。示例: *.timinglee.org
www.timinglee.*
regular expression: #被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:
~.*\.timinglee\.com
正常通过搜索引擎搜索web 网站并访问该网站的referer信息如下:
172.25.254.1 - - [22/Jul/2024:09:27:36 +0800] "GET /favicon.ico HTTP/1.1" 404 149 "http://lee.timinglee.org/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0" 2024/07/22 09:27:36 [error] 34596#0: *205 open() "/webdata/nginx/timinglee.org/lee/favicon.ico" failed (2: No such file or directory), client: 172.25.254.1, server: lee.timinglee.org, request: "GET /favicon.ico HTTP/1.1", host: "lee.timinglee.org", referrer: "http://lee.timinglee.org/"
实现盗链:
在一个web 站点盗链另一个站点的资源信息,比如:图片、视频等
#新建一个主机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"
实现防盗链
[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
六 Nginx 反向代理功能
反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的 一种方式,这是用的比较多的一种方式。
Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预 定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主 要在不同的场景使用以下模块实现不同的功能
同构代理:用户不需要其他程序的参与,直接通过http协议或者tcp协议访问后端服务器
异构代理:用户访问的资源时需要经过处理后才能返回的,比如php,python,等等,这种访问资源需 要经过处理才能被访问
6.1 实现 http 反向代理
#官方文档: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://1:8080
#重启Nginx测试访问效果:
#curl -L http://www.timinglee.org/web
# http://nginx/web/index.html ==>
#如果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_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在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请求后,等待的超时时间,默认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
指定location实现反向代理(动静分离)
环境:一台WEBSERVERIP为10和两台RSIP为100&200
在RS1上做静态
dnf install httpd -y
mkdir /var/www/html/static/
echo 172.25.254.100 static > /var/www/html/static/index.html
在100上写入网站首页内容并修改端口为8080:
vim /etc/httpd/conf/httpd.conf
在RS2上做动态
dnf install httpd -y
dnf install php -y
systemctl restart httpd
mkdir /var/www/html/php/
vim /var/www/html/php/index.php
做访问全站代理,虽然要访问的是www.timinglee.org,但是给你返回的却是172.25.254.100的内容
只要是PHP结尾的请求,返回的都是172.25.254.200的内容,其他的请求都是返回100的内容
测试:
当访问www.timinglee.org/static/时:
当访问www.timinglee.org/index.php/时:
做访问全站代理,虽然要访问的是www.timinglee.org,但是给你返回的却是172.25.254.100的内容
只要是PHP结尾的请求,返回的都是172.25.254.200的内容,其他的请求都是返回100的内容
6.2 反向代理示例: 缓存功能
缓存功能默认关闭状态,需要先动配置才能启用
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
2^4x2^8x2^8=2^20=1048576个目录
keys_zone=proxycache:20m
(如:使用次数)
#定义缓存目录结构层次
#1:2:2可以生成
#指内存中缓存的大小,主要用于存放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 ;
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
#示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
这里是在RS2上做www.timinglee.org的域名解析
测试对资源的缓存
在nginx配置文件里
再次缓存资源,改善了缓存速度
6.3 实战案例: 反向代理单台 web 服务器
要求:将用户对域 www.timinglee.org 的请求转发给后端服务器处理
[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.4 实战案例: 指定 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并访问测试:
[2024-07-25 17:09.35] ~
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org/static/
static 172.25.254.20
[2024-07-25 17:09.39] ~
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.30
6.3 针对特定的资源实现代理
[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.4 nginx负载均衡的反向代理
在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而 且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提 供服务器分组转发、权重分配、状态监测、调度算法等高级功能
# ============ 自定义后端服务器组 ============
# 写在 http { } 块内
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s max_conns=1000;
server unix:/tmp/backend3;
server backup1.example.com backup; # 仅当全部节点挂掉时启用
# server old-node.example.com down; # 平滑下线
}# ------------ 调度算法示例 ------------
# 1. 加权轮询(默认)
# 2. 最少连接
# least_conn;# 3. IP 会话保持
# ip_hash;# 4. URI 一致性哈希
# hash $request_uri consistent;# 5. Cookie 会话保持
# hash $cookie_sessionid consistent;# ------------ server 指令参数速查 ------------
# weight=N 权重,默认 1(WRR/WLC)
# max_conns=N 节点最大并发,0=无限制
# max_fails=N 连续失败 N 次后标记不可用
# fail_timeout=T 失败后的重试间隔,默认 10s
# backup 备用节点
# down 手动下线
# resolve 主机名 A 记录变化时自动生效(需 nginx 1.5.8+)
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;
error_log logs/dns.log;
}
}
测试:
# 使用UDP协议时,设置代理服务器响应客户端期望的数据报文数
# 该值作为会话的终止条件
[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
8888
6.5 udp 负载均衡实例: DNS
在RS1和RS2上配置DNS
vim /etc/name.conf
vim /etc/name.rfc1912.zones
cd /var/named/
[named] cp -p named.localhost "timinglee.org.zone"
[named] vim "timinglee.org.zone"
最后记得重启服务
systemctl restart named
在RS2上也要做一样的操作
测试DNS是否生效
dns配置完成
在nginx上配置:
在主配置文件中添四层代理的子配置目录
这里53开启的是udp
这里tcp、udp都开53端口
测试: 启动两台server的dns,并且查看是否解析成功:
6.5 负载均衡实例: MySQL
后端服务器安装 MySQL
#在apache20中安装mysql
[root@apache20 ~]# yum install mariadb-server -y
[root@apache20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=20
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 |
+-------------+
|
#在apache30重复以上步骤并在apache20上测试
nginx配置
[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 |
+-------------+
7.FastCGI
不是协议,一种规则
Nginx不能对php进行解析,它们之间要怎么沟通呢?
就要用到CGI了
php的模式就是有连接时就开机,完成链接有就关闭,下次再来再开机,这样的来回开关,会造成很多的损耗,这是有要用到FastCGI来管理了
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代码的处理。
7.1 FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处 理,其配置指令如下:
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
fastcgi_param REMOTE_PORT
fastcgi_param SERVER_ADDR
fastcgi_param SERVER_PORT
fastcgi_param SERVER_NAME
Nginx默认配置示例:
location ~ \.php$ {
root
fastcgi_pass
$remote_addr; #客户端源IP
$remote_port; #客户端源端口
$server_addr; #请求的服务器IP地址
$server_port; #请求的服务器端口
$server_name; #请求的server name
/scripts;
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
}
7.2 FastCGI实战案例 : Nginx与php-fpm在同一服务器
编译安装更方便自定义参数或选项,所以推荐大家使用源码编译 官方网站: www.php.net
源码编译php
# 1. 安装依赖
yum install -y \
bzip2 systemd-devel libxml2-devel sqlite-devel \
libpng-devel libcurl-devel oniguruma-devel
# 2. 解压源码后进入目录
cd php-8.x.x # 替换为你的源码目录
# 3. 一键配置(含优化)
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--enable-fpm \
--with-fpm-user=nginx \
--with-fpm-group=nginx \
--with-fpm-systemd \
--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
# 4. 编译安装
make -j$(nproc) && make install
php相关配置优化
[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
820758
0 127.0.0.1:9000
0.0.0.0:*
LISTEN
0
176202/php-fpm: mas
进入php目录
没有配置文件只有模版
复制到php文件里
修改监听端口
生成主配置文件
[root@php ~]# cd /root/php-8.3.9/
[root@php php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
#修改主配置文件的时区
[root@php php-8.3.9]# vim /usr/local/php/etc/php.ini
[root@php php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
[root@php php-8.3.9]# vim /lib/systemd/system/php-fpm.service
重启服务
[root@php php-8.3.9]# systemctl start php-fpm.service
[root@php php-8.3.9]# netstat -antlupe | grep php
准备php测试页面
[root@Nginx ~]# mkdir /data/php -p
[root@centos8 ~]# cat /data/php/index.php #php测试页面
<?php
phpinfo();
?>
Nginx配置转发
Nginx安装完成之后默认生成了与fastcgi的相关配置文件,一般保存在nginx的安装路径的conf目录当 中,比如/apps/nginx/conf/fastcgi.conf、/apps/nginx/conf/fastcgi_params。
[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@php conf]# vim /usr/local/nginx/conf/nginx.conf
[root@php conf]# systemctl start nginx.service
[root@php conf]# nginx -s reload
7.3 php的动态扩展模块(php的缓存模块)
安装memcache模块
[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-non
zts-20230831/
[root@Nginx memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts
20230831/
memcache.so opcache.so
手动添加memcache
再次查看就有了
查看配置文件的命令
复制测试文件到nginx发布目录中
[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 run
tests.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');
define('ADMIN_PASSWORD','lee');
// Admin Username
// 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
配置php加载memcache模块
[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
部署memcached
[root@Nginx ~]# yum install memcached -y
[root@Nginx ~]# systemctl enable --now memcached.service
[root@Nginx ~]# netstat -antlupe | grep memcache
tcp
0
976
1037243
0 127.0.0.1:11211
186762/memcached
0.0.0.0:*
[root@Nginx ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"
它开启的端口,所有的都可以访问
放在自己默认的地方
memcache.php查看命中的,用来测试的
初次访问时要输入用户和密码,所以修改一下
测试:
访问 http://php.timinglee.org/example.php 不断刷新 访问 http://php.timinglee.org/memcache.php 查看命中效果
性能对比
7.4 php高速缓存
在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所 以nginx需要重新编译
rm -fr /apps/nginx/
tar zxf srcache-nginx-module-0.33.tar.gz
tar zxf memc-nginx-module-0.20.tar.gz
# 编译安装
cd /root/nginx-1.26.1
./configure \
--prefix=/apps/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
make -j$(nproc) && make install
/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;
set $memc_exptime 300;
memc_pass memcache;
}
# PHP 请求:先查缓存 → 再执行 → 再缓存
location ~ \.php$ {
set $key $uri$args;
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
systemctl start nginx.service
memcache设置长连接
内部调用
send发送超时时间
read
键值数据库,对键值制定
超时时间300s
uri指定key是什么值
当get一个东西时,会去找key值(key值在上面指定了)如果这两个都没找到,就会继续运行下面的
压力测试
memcache前置了,memcache既可以取值又可以缓存,实现高速缓存
7.5 nginx 二次开发版本-openresty
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/
[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