在Linux中模拟配置高性能web服务器

在Linux中模拟配置高性能web服务器

一.Web 服务基础介绍

正常情况下的单次web服务访问流程:

1.Web服务介绍

1.1Apache经典的Web服务端

Apache起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发 目前经历了两大版本分别是1.X和2.X 其可以通过编译安装实现特定的功能

1.2Apache prefork模型
  • 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
  • 每个子进程有一个独立的线程响应用户请求
  • 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
  • 是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景

优点:稳定

缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景

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

优点:相比prefork 占用的内存较少,可以同时处理更多的请求 缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)

1.4Apache event模型

Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)

每个进程响应多个请求,在现在版本里的已经是稳定可用的模式 它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)

event MPM中,会有一个专门的线程来管理这些keepalive类型的线程

当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力

优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放

缺点:没有线程安全控制

1.5Nginx-高性能的Web服务端

Nginx历经十几年的迭代更新( https://nginx.org/en/CHANGES), 目前功能已经非常完善且运行稳 定,另外Nginx的版本分为开发版、稳定版和过期版,nginx以功能丰富著称,它即可以作为http服务 器,也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求

支持FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以 上且开启stream模块)等功能,并且支持第三方的功能扩展。

一线互联网公司都在用Nginx或者进行二次开发

基于Nginx的工作场景:

1.6影响用户体验的因素

1.客户端

  • 客户端硬件配置
  • 客户端网络速率
  • 客户端与服务端距离

2.服务器

  • 服务端网络速率
  • 服务端硬件配置
  • 服务端架构设计
  • 服务端应用程序工作模式
  • 服务端并发数量服务端响应文件大小及数量 buffer cache
  • 服务端I/O压力1.2.4 服务端 I/O 流程
1.7服务端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.8磁盘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.9网络I/O

网络通信就是网络协议栈到用户空间进程的IO就是网络IO

网络I/O处理过程

  • 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
  • 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
  • 返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)

不论磁盘和网络I/O

每次I/O,都要经由两个阶段:

  • 第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
  • 第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短

2.I/O模型

2.1I/O 模型相关概念

同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状 态的通知。

  • 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成
  • 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态

阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态

  • 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂 起,干不了别的事情。
  • 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完 成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
2.2网络I/O模型

阻塞型、非阻塞型、复用型、信号驱动型、异步

2.2.1 阻塞型 I/O 模型(blocking IO)
  • 阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
  • 用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然 后将接收的数据拷贝到用户空间,完成read操作
  • 用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线 程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够

优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源

缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销 较apache 的preforck使用的是这种模式。

同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进 程将一直等待并不再接受新的请求,并由进程轮询查看I/O是否完成,完成后进程将I/O结果返回给 Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种 方式简单,但是比较慢,用的比较少。

2.2.2 非阻塞型 I/O 模型 (nonblocking IO)

用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据 到达后,才真正读取到数据,继续执行。即 "轮询"机制存在两个问题:如果有大量文件描述符都要等, 那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户 态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长, 程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一 般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。

非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结 果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完 成。

查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返 回一个 EWOULDBLOCK 错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准 备好了,所以这时数据会被复制到 应用进程缓冲区 ,于是 recvfrom 成功返回数据

当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实 际使用很少

2.2.3 多路复用 I/O 型(I/O multiplexing)

上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理

多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自 的IO,即复用同一个线程

一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调 用,从而实现多路复用IO

I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个 process就可以同时处理多个网络连接的IO。

它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数 据到达了,就通知用户进程。

当用户进程调用了select,那么整个进程会被block,而同时,kernel会"监视"所有select负责的socket, 当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从 kernel拷贝到用户进程。

Apache prefork是此模式的select,worker是poll模式。

IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示"我要监视这些fd是否有IO事件发生,有了就告诉程序处理"IO多路复用一般和NIO一起使用的。NIO和IO多路 复用是相对独立的。NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统 提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时还是当前线程被卡住。IO多路复用和NIO是要配合一起使用才有实际意义

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程多个连接共用一 个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行从流程上来看,使用 select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的 额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已 有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只 能监控一个IO虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select 函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然 后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率IO多路复用是最常使用的IO 模型,但是其异步程度还不够"彻底",因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称 为异步阻塞IO模型,而非真正的异步IO

优缺点

  • 优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述 符一个线程),这样可以大大节省系统资源
  • 缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理 需要 2 次系统调用,占用时间会有增加

IO多路复用适用如下场合:

  • 当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
  • 当一个客户端同时处理多个套接字时,此情况可能的但很少出现
  • 当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
  • 当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
  • 当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
2.2.4 信号驱动式 I/O 模型 (signal-driven IO)

信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知 进程。

调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO信 号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进 程所需要的数据从内核空间拷贝到用户空间

此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处 理函数的通知。

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续 运行并不阻塞

当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此 可以提高资源的利用率

缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知

异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程 请求后 进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。

2.2.5 异步 I/O 模型 (asynchronous IO)

异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O 是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把 等待上菜的时间也给省了

相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直 接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。

信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到 用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续 操作了

优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠

缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的 异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编 程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求

Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、 libuv。

异步非阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的 IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的 结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现 较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。

2.2.6五种IO对比

这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步 I/O,因为其中真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配

2.2.7 I/O 的具体实现方式
2.2.7.1 I/O常见实现

Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统 版本上面的实现方式不尽相同,主要有以下实现方式:

1、select: select库是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是 部分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。

2、poll: 在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在 编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。

3、epoll: epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和 select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.epoll的处理方式是创建一个 待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮询检查这个表,以判断事件是否发 生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的 I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的"活跃"的描述符进行操作。

4、kqueue: 用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版 本NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别, 都是通过避免轮询操作提供效率。

5、Iocp: Windows系统上的实现方式,对应第5种(异步I/O)模型。

6、rtsig: 不是一个常用事件驱动,最大队列1024,不是很常用

7、/dev/poll: 用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发 Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员 将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的 时候请使用/dev/poll事件驱动机制。

8、eventport: 该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防 止内核崩溃等情况的发生。

用源码安装nginx

检查依赖性

bash 复制代码
[root@webserver nginx-1.24.0]# ./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
复制代码
[root@webserver nginx-1.24.0]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin


[root@webserver nginx-1.24.0]# source ~/.bash_profile


[root@webserver nginx-1.24.0]# nginx -V
nginx version: nginx/1.24.0
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module

平滑升级和回滚

平滑升级

bash 复制代码
[root@webserver sbin]#

[root@webserver sbin]# ll
total 1208
-rwxr-xr-x 1 root root 1234424 Jul 24 10:54 nginx

[root@webserver sbin]# mv nginx nginx.old

[root@webserver sbin]# /bin/cp -f /mnt/nginx-1.26.3/objs/nginx /usr/local/nginx/sbin/

[root@webserver sbin]# ll
total 2420
-rwxr-xr-x 1 root root 1239480 Jul 24 10:58 nginx
-rwxr-xr-x 1 root root 1234424 Jul 24 10:54 nginx.old

[root@webserver 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@webserver sbin]# ps aux | grep nginx
root        4809  0.0  0.0   9868  2052 ?        Ss   10:47   0:00 nginx: master process nginx
nginx       4810  0.0  0.1  14200  5252 ?        S    10:47   0:00 nginx: worker process
root        4891  0.0  0.0   6408  2176 pts/0    S+   10:59   0:00 grep --color=auto nginx

[root@webserver sbin]# curl -I 172.25.254.10
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Thu, 24 Jul 2025 02:59:25 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 23 Jul 2025 07:43:14 GMT
Connection: keep-alive
ETag: "68809292-267"
Accept-Ranges: bytes

[root@webserver sbin]# kill -USR2 4809

[root@webserver sbin]# ps aux | grep nginx
root        4809  0.0  0.0   9868  2436 ?        Ss   10:47   0:00 nginx: master process nginx
nginx       4810  0.0  0.1  14200  5252 ?        S    10:47   0:00 nginx: worker process
root        4893  0.0  0.1   9876  6400 ?        S    10:59   0:00 nginx: master process nginx
nginx       4894  0.0  0.1  14208  4996 ?        S    10:59   0:00 nginx: worker process
root        4896  0.0  0.0   6408  2176 pts/0    S+   10:59   0:00 grep --color=auto nginx

[root@webserver sbin]# kill -WINCH 4809

[root@webserver sbin]# ps aux | grep nginx
root        4809  0.0  0.0   9868  2436 ?        Ss   10:47   0:00 nginx: master process nginx
root        4893  0.0  0.1   9876  6400 ?        S    10:59   0:00 nginx: master process nginx
nginx       4894  0.0  0.1  14208  4996 ?        S    10:59   0:00 nginx: worker process
root        4898  0.0  0.0   6408  2176 pts/0    S+   11:00   0:00 grep --color=auto nginx

[root@webserver sbin]# curl -I 172.25.254.10
HTTP/1.1 200 OK
Server: BrandonX/
Date: Thu, 24 Jul 2025 03:00:27 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 23 Jul 2025 07:43:14 GMT
Connection: keep-alive
ETag: "68809292-267"
Accept-Ranges: bytes

[root@webserver sbin]# kill -9 4809
[root@webserver sbin]# ps aux | grep nginx
root        4956  0.0  0.1   9876  6528 ?        S    11:07   0:00 nginx: master process nginx
nginx       4957  0.0  0.1  14208  5252 ?        S    11:07   0:00 nginx: worker process
root        4964  0.0  0.0   6408  2176 pts/0    S+   11:08   0:00 grep --color=auto nginx

回退

复制代码
[root@webserver sbin]# ps aux | grep nginx
root        4809  0.0  0.0   9868  2436 ?        Ss   10:47   0:00 nginx: master process nginx
nginx       4941  0.0  0.1  14200  5252 ?        S    11:04   0:00 nginx: worker process
root        4945  0.0  0.0   6408  2176 pts/0    S+   11:05   0:00 grep --color=auto nginx
[root@webserver sbin]# curl -I 172.25.254.10
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Thu, 24 Jul 2025 03:05:26 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 23 Jul 2025 07:43:14 GMT
Connection: keep-alive
ETag: "68809292-267"
Accept-Ranges: bytes

隐藏版本信息

复制代码
[root@webserver mnt]# cd nginx-1.26.3/
[root@webserver nginx-1.26.3]# vim src/core/nginx.h

创建systemd服务

bash 复制代码
#查看模板
#可以直接在baidu搜systemd site:nginx.org
https://mailman.nginx.org/pipermail/nginx/2017-April/053368.html
bash 复制代码
vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t									#检查nginx配置文件语法
ExecStart=/usr/local/nginx/sbin/nginx										#启动服务
ExecReload=/bin/kill -s HUP $MAINPID										#重新加载
ExecStop=/bin/kill -s QUIT $MAINPID											#停止服务
PrivateTmp=true
[Install]
WantedBy=multi-user.target

实现 nginx 的高并发配置

bash 复制代码
[root@webserver ~]# ulimit -n num
num
#临时修改设置单个进程可打开的最大文件描述符数量


[root@webserver ~]# vim /etc/security/limits.conf
*               -       nofile          100000				#添加这两行	* 是所有用户 - 是软线和硬线
*               -       nproc           100000				

# End of file
这里后面跟的100000就是你要更改的数字

更改完成后

复制代码
重新开一个shell,ctrl + D
让系统重新加载一下配置
[root@webserver ~]# ulimit -n
100000
bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf/nginx.conf
#注意这里的路径是我把nginx安装在这个路径底下了
#务必检查是否是这个路径
#下图则是要更改的参数和配置
[root@webserver ~]# locate nginx.conf
/usr/local/nginx/conf/nginx.conf
/usr/local/nginx/conf/nginx.conf.default
#也可以通过locate命令去协助查找nginx.conf这个文件

更改完nginx.conf后,务必重启nginx,让nginx重新加载配置文件

bash 复制代码
[root@webserver ~]# nginx -t			#先检查nginx配置文件的语法有无错误
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@webserver ~]# nginx -s reload		#没有错误的话可以让nginx重新加载配置了

ab压测

ab -c 单次发送 -n 总数 要压力的ip 每次发5000个,一共100000个

复制代码
[root@webserver ~]# ab -c 5000 -n 100000 http://172.25.254.10/index.html
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 172.25.254.10 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        BrandonX/
Server Hostname:        172.25.254.10
Server Port:            80

Document Path:          /index.html
Document Length:        615 bytes

Concurrency Level:      5000
Time taken for tests:   4.214 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      84500000 bytes
HTML transferred:       61500000 bytes
Requests per second:    23728.84 [#/sec] (mean)
Time per request:       210.714 [ms] (mean)
Time per request:       0.042 [ms] (mean, across all concurrent requests)
Transfer rate:          19580.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        2  100  36.1     95     257
Processing:    32  105  25.3    103     322
Waiting:        0   67  27.3     64     162
Total:        118  205  32.4    198     378

Percentage of the requests served within a certain time (ms)
  50%    198
  66%    206
  75%    209
  80%    213
  90%    226
  95%    248
  98%    343
  99%    347
 100%    378 (longest request)

用户认证

bash 复制代码
#错误操作
[root@webserver nginx]# htpasswd -cm /usr/local/nginx/conf/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin

[root@webserver nginx]# htpasswd -cm /usr/local/nginx/conf/.htpasswd vb
New password:
Re-type new password:
Adding password for user vb

#注意上面用了两次-c参数,-c参数是创建的意思,第二次用-c参数时覆盖了第一次创建的信息

[root@webserver nginx]# cat /usr/local/nginx/conf/.htpasswd
vb:$apr1$McUkFXI.$XDpwrHus2PkCA31Fp3ort0
bash 复制代码
[root@webserver nginx]# htpasswd -cm /usr/local/nginx/conf/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin

[root@webserver nginx]# htpasswd -m /usr/local/nginx/conf/.htpasswd vb
New password:
Re-type new password:
Adding password for user vb

[root@webserver nginx]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$qdRgF8yx$id1sZSKYeIkIka5Vri1x0.
vb:$apr1$w8kAEu8h$f9199XWiXp5fC.pZoU1QZ0
#所以当我们要添加第二个用户时,应该只用-m参数
复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
	location /login/ {
        root /web/ ;
        auth_basic "Please input your name and password:" ;
        auth_basic_user_file "/usr/local/nginx/conf/.htpasswd" ;
    }

[root@webserver ~]# mkdir -p /web/login
[root@webserver ~]# echo login page > /web/login/index.html

[root@webserver nginx]# nginx -t
[root@webserver ~]# nginx -s reload

[root@webserver ~]# curl  www.vb.org/login/
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>BrandonX/</center>
</body>
</html>

[root@webserver ~]# curl -uadmin  www.vb.org/login/
Enter host password for user 'admin':
login page

自定义错误页面

bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
	.....
	error_page      500 502 503 504 404 403 /error.html;
	.....
	location /error.html {
        root /web/error/;
    }
    ......
}
[root@webserver ~]# mkdir /web/error
[root@webserver ~]# echo error page > /web/error/error.html

[root@webserver ~]# nginx -s reload
[root@webserver ~]# curl www.vb.org/abaaa
error page

自定义错误日志输出

复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {	
	error_log       /usr/local/nginx/logs/vb.org.error;
    access_log      /usr/local/nginx/logs/vb.org.access;
	......
	location xxx
	......
}

[root@webserver ~]# nginx -s reload
[root@webserver ~]# curl www.vb.org
www.vb.org
[root@webserver ~]# cat /usr/local/nginx/logs/vb.org.access
172.25.254.10 - - [26/Jul/2025:10:40:50 +0800] "GET / HTTP/1.1" 200 11 "-" "curl/7.76.1"
[root@webserver ~]# cat /usr/local/nginx/logs/vb.org.error
[root@webserver ~]# curl www.vb.org/ahsdhjahfh
error page
[root@webserver ~]# cat /usr/local/nginx/logs/vb.org.error
2025/07/26 10:41:06 [error] 2028#0: *22 open() "/web/html/ahsdhjahfh" failed (2: No such file or directory), client: 172.25.254.10, server: www.vb.org, request: "GET /ahsdhjahfh HTTP/1.1", host: "www.vb.org"

检测文件是否存在

try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一 个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内部500错误。

bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
server{
	......
	root xxxxxxxx
	#注意这里写的位置是在server里面,所以路径是root/error/default.html
	try_files $uri $uri.html $uri/index.html /error/default.html;
	......
	location
	......
}

[root@webserver ~]# mkdir -p /web/html/error/

[root@webserver ~]# echo "index.html is not exist,this is a default page" > /web/html/error/default.html

[root@webserver ~]# nginx -s reload

[root@webserver ~]# curl www.vb.org/b
index.html is not exist,this is a default page

长连接配置

超时时间
bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf/nginx.conf
http{
	......
	keepalive_timeout  5;
	......
}
bash 复制代码
[root@webserver ~]# dnf install telnet -y

[root@webserver ~]# telnet 172.25.254.10 80
Trying 172.25.254.10...
Connected to 172.25.254.10.
Escape character is '^]'.
GET / HTTP/1.1
Host: 172.25.254.10

HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 03:32:47 GMT
Content-Type: text/html
Content-Length: 27
Last-Modified: Thu, 24 Jul 2025 08:01:12 GMT
Connection: keep-alive
ETag: "6881e848-1b"
Accept-Ranges: bytes

index.html - 172.25.254.10
Connection closed by foreign host.

#实际测试过了五秒就自动断开了
#因为我们在nginx的主配置文件设定的是5秒
#注意:这里只是测试用5秒,实际上5秒的设定是不合理的
#一般设定为60秒或者65秒
传输包指定个数后断开长链接
复制代码
[root@webserver ~]# vim /usr/local/nginx/conf/nginx.conf
http{
	......
	keepalive_requests 3;
    keepalive_timeout  65;
	......
}
bash 复制代码
[root@webserver ~]# telnet 172.25.254.10 80
Trying 172.25.254.10...
Connected to 172.25.254.10.
Escape character is '^]'.
GET / HTTP/1.1
Host: 172.25.254.10

HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 03:35:07 GMT
Content-Type: text/html
Content-Length: 27
Last-Modified: Thu, 24 Jul 2025 08:01:12 GMT
Connection: keep-alive
ETag: "6881e848-1b"
Accept-Ranges: bytes

index.html - 172.25.254.10
GET / HTTP/1.1
Host: 172.25.254.10

HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 03:35:23 GMT
Content-Type: text/html
Content-Length: 27
Last-Modified: Thu, 24 Jul 2025 08:01:12 GMT
Connection: keep-alive
ETag: "6881e848-1b"
Accept-Ranges: bytes

index.html - 172.25.254.10
GET / HTTP/1.1
Host: 172.25.254.10

HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 03:35:33 GMT
Content-Type: text/html
Content-Length: 27
Last-Modified: Thu, 24 Jul 2025 08:01:12 GMT
Connection: close
ETag: "6881e848-1b"
Accept-Ranges: bytes

index.html - 172.25.254.10
Connection closed by foreign host.

#经过三次报文后自动断开长连接

下载服务器

11111111111111111111111111111111111

bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf

server{
	location /download {
        root /web/;
        autoindex on;
        autoindex_exact_size on;
        autoindex_localtime on;
        autoindex_format html;
        set $limit_rate 1024k;
    }
}
bash 复制代码
[root@webserver ~]# mkdir /web/download/ -p

#创建实验素材
[root@webserver ~]# dd if=/dev/zero of=/web/download/vb bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 1.057 s, 496 MB/s


#限速前
[root@webserver ~]# wget www.vb.org/download/vb
--2025-07-26 11:49:32--  http://www.vb.org/download/vb
Resolving www.vb.org (www.vb.org)... 172.25.254.10
Connecting to www.vb.org (www.vb.org)|172.25.254.10|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 524288000 (500M) [application/octet-stream]
Saving to: 'vb'

vb                               100%[==========================================================>] 500.00M   308MB/s    in 1.6s

2025-07-26 11:49:33 (308 MB/s) - 'vb' saved [524288000/524288000]



#限速后
[root@webserver ~]# wget www.vb.org/download/vb
--2025-07-26 11:48:20--  http://www.vb.org/download/vb
Resolving www.vb.org (www.vb.org)... 172.25.254.10
Connecting to www.vb.org (www.vb.org)|172.25.254.10|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 524288000 (500M) [application/octet-stream]
Saving to: 'vb'

vb                                 1%[                                                           ]   7.00M  1.01MB/s    eta 8m 10s ^C


[root@webserver ~]# curl www.vb.org/download/
<html>
<head><title>Index of /download/</title></head>
<body>
<h1>Index of /download/</h1><hr><pre><a href="../">../</a>
<a href="vb">vb</a>                                                 26-Jul-2025 11:47           524288000
</pre><hr></body>
</html>


[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@webserver ~]# nginx -s reload
[root@webserver ~]# curl www.vb.org/download/
<html>
<head><title>Index of /download/</title></head>
<body>
<h1>Index of /download/</h1><hr><pre><a href="../">../</a>
<a href="vb">vb</a>                                                 26-Jul-2025 11:47    500M
</pre><hr></body>
</html>

状态页

复制代码
server {
	......
	location /status {
        stub_status;
        auth_basic "Please input your name and password:" ;
        auth_basic_user_file "/usr/local/nginx/conf/.htpasswd" ;
    }
    ......
}

压缩上传

复制代码
[root@webserver ~]# echo hello > /usr/local/nginx/html/small.html

[root@webserver ~]# du -sh /var/log/messages
1.1M    /var/log/messages
[root@webserver ~]# cp /var/log/messages /usr/local/nginx/html/big.html


http {
	gzip  on;
    gzip_comp_level 4;
    gzip_disable "MSIE [1-6]\.";
    gzip_min_length 4k;
    gzip_vary on;
    gzip_static on;
}
bash 复制代码
[root@webserver ~]# du -sh /usr/local/nginx/html/big.html
1.1M    /usr/local/nginx/html/big.html
[root@webserver ~]# du -sh /usr/local/nginx/html/small.html
4.0K    /usr/local/nginx/html/small.html


[root@webserver ~]#  curl --head --compressed 172.25.254.10/big.html
HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 06:56:18 GMT
Content-Type: text/html
Last-Modified: Sat, 26 Jul 2025 06:44:49 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"68847961-118512"
Content-Encoding: gzip

[root@webserver ~]#  curl --head --compressed 172.25.254.10/small.html
HTTP/1.1 200 OK
Server: BrandonX/
Date: Sat, 26 Jul 2025 06:56:22 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Sat, 26 Jul 2025 06:41:23 GMT
Connection: keep-alive
ETag: "68847893-6"
Accept-Ranges: bytes

版本隐藏

用户在访问nginx的时候,我们可以从报文中获得nginx的版本,相对于裸漏版本号的nginx,我们把其隐 藏起来更安全

bash 复制代码
[root@webserver ~]# vim /mnt/nginx-1.26.3/src/core/nginx.h	#注意这个地址是你安装nginx的地址
#define nginx_version      1026003
#define NGINX_VERSION      ""
#define NGINX_VER          "BrandonX/" NGINX_VERSION

变量

bash 复制代码
server{
	......
	location /vars {
        default_type text/html;
        echo $uri;
        echo $remote_addr;
        echo $args;
        echo $is_args;
        echo $arg_name;
        echo $document_root;
        echo $document_uri;
        echo $host;
        echo $remote_port;
        echo $remote_user;
        echo $request_method;
        echo $request_filename;
        echo $request_uri;
        echo $scheme;
        echo $server_protocol;
        echo $server_addr;
        echo $server_name;
        echo $server_port;
        echo $http_user_agent;
        echo $http_cookie;
        echo $cookie_key1;
        echo $http_HOST;
    }
    ......
}
复制代码
[root@webserver nginx-1.26.3]# curl -A "Brandon" -b "vb=b,key1=2" -uvb:vb www.vb.org/vars?name=vb
/vars
172.25.254.10
name=vb
?
vb
/web/html
/vars
www.vb.org
53880
vb
GET
/web/html/vars
/vars?name=vb
http
HTTP/1.1
172.25.254.10
www.vb.org
80
Brandon
vb=b,key1=2
2
www.vb.org

临时重定向和永久重定向

复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
server{
	......
	location /aaa {
        rewrite ^/aaa http://www.vb.org permanent;
    }
    location /bbb {
        rewrite ^/bbb http://www.vb.org redirect;
    }
    ......
}
[root@webserver ~]# 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@webserver ~]# nginx -s reload

[root@webserver ~]# curl www.vb.org/aaa
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>BrandonX/</center>
</body>
</html>
[root@webserver ~]# curl www.vb.org/bbb
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>BrandonX/</center>
</body>
</html>

break&last

复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf




[root@webserver ~]# mkdir -p /web/html/{break,test1,vb}
[root@webserver ~]# ll /web/html/
total 4
drwxr-xr-x 2 root root  6 Jul 27 10:37 break
drwxr-xr-x 2 root root 26 Jul 26 11:26 error
-rw-r--r-- 1 root root 11 Jul 24 16:05 index.html
drwxr-xr-x 2 root root  6 Jul 27 10:37 test1
drwxr-xr-x 2 root root  6 Jul 27 10:37 vb
[root@webserver ~]# echo vbvbvbvbvbvb > /web/html/vb/index.html
[root@webserver ~]# echo test1 > /web/html/test1/index.html

全站加密

防盗链

反向代理

动静分离

bash 复制代码
vmset.sh eth0 172.25.254.100 RS1
[root@RS1 ~]# dnf install php httpd -y
echo RS1 - static - 172.25.254.100 > /var/www/html/static/index.html
systemctl enable --now httpd
systemctl disable --now firewalld
bash 复制代码
vmset.sh eth0 172.25.254.200 RS2
[root@RS2 ~]# dnf install php httpd -y
mkdir /var/www/html/php
vim /var/www/html/php/index.php
<?php
  phpinfo()
?>

systemctl disable --now firewalld.service
systemctl enable --now httpd

缓存

负载均衡的反向代理

基于Cookie 实现会话绑定

dns四层负载均衡

源码编译安装php

bash 复制代码
[root@webserver php-8.3.9]# tar zxf php-8.3.9.tar.gz


[root@webserver php-8.3.9]# cd php-8.3.9/

#检测依赖
[root@webserver php-8.3.9]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=nginx  --with-fpm-group=nginx --with-curl --with-iconv --with-mhash --with-zlib --with-openssl --enable-mysqlnd --with-mysqli --with-pdo-mysql --disable-debug --enable-sockets --enable-soap  --enable-xml  --enable-ftp --enable-gd  --enable-exif --enable-mbstring  --enable-bcmath  --with-fpm-systemd

#安装依赖文件
[root@webserver php-8.3.9]# dnf whatprovides */libsystemd.so                    
[root@webserver php-8.3.9]# dnf install systemd-devel-252-32.el9_4.x86_64 -y    
[root@webserver php-8.3.9]# dnf whatprovides */libxml-2.0.pc                    
[root@webserver php-8.3.9]# dnf install libxml2-devel-2.9.13-5.el9_3.x86_64 -y  
[root@webserver php-8.3.9]# dnf install sqlite-devel.x86_64 -y                  
[root@webserver php-8.3.9]# dnf install libcurl-devel.x86_64 -y                 
[root@webserver php-8.3.9]# dnf install libpng-devel.x86_64 -y                  

#其中我的环境中有一个依赖版本不对,在网上下载用rpm -ivh进行安装
[root@webserver php-8.3.9]# rpm -ivh oniguruma-6.9.6-1.el9.6.x86_64.rpm
[root@webserver php-8.3.9]# rpm -ivh oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm
#然后用dnf安装升级
[root@webserver php-8.3.9]# dnf install oniguruma-6.9.6-1.el9.6.x86_64.rpm      
[root@webserver php-8.3.9]# dnf install oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm

#编译成功后编译安装
[root@webserver php-8.3.9]# make && make install                                
bash 复制代码
[root@webserver ~]# cd /usr/local/php/etc/
[root@webserver etc]# cp php-fpm.conf.default php-fpm.conf

[root@webserver ~]# find / -name php-fpm.pid
/usr/local/php/var/run/php-fpm.pid

[root@webserver etc]# vim php-fpm.conf
#去掉分号,取消注释
pid = run/php-fpm.pid       #指定pid文件存放位置
bash 复制代码
[root@webserver etc]# cd php-fpm.d/
[root@webserver php-fpm.d]# cp www.conf.default www.conf
bash 复制代码
#生成主配置文件
[root@webserver ~]# cd /root/php-8.3.9/
[root@webserver php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini

修改时区

避免时区错乱

bash 复制代码
#修改时区
[root@webserver php-8.3.9]# 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
bash 复制代码
#生成启动文件
[root@webserver php-8.3.9]# vim /lib/systemd/system/php-fpm.service
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by this unit.
#ProtectSystem=full				#注释该内容
bash 复制代码
[root@webserver php-8.3.9]# systemctl start php-fpm.service
[root@webserver php-8.3.9]# systemctl enable --now php-fpm.service
Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service.
[root@webserver php-8.3.9]# netstat -antlupe | grep php
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      0          335889     201267/php-fpm: mas

准备php测试页面

bash 复制代码
[root@webserver php-8.3.9]# mkdir /web/php -p
[root@webserver php-8.3.9]# vim /web/php/index.php
<?php
  phpinfo();
?>

!!!这步不是必须!!!只是我的实验环境不是初始状态!!!

bash 复制代码
[root@webserver ~]# vim /usr/local/nginx/conf.d/vhost.conf
#如下图注释

由于在之前的实验中做了缓存实验和匹配.php后缀实验,所以开启这些会影响接下来的实验效果

bash 复制代码
[root@webserver ~]# vim  /usr/local/nginx/conf.d/php.conf
server {
    listen 80;
    server_name php.vb.org;
    root /web/php/;
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}

在浏览器中测试访问

如果成功看到这个页面,那么恭喜你 你是这个👍

环境变量

bash 复制代码
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# User specific environment and startup programs
export PATH=$PATH:/usr/local/nginx/sbin:/usr/local/php/bin
bash 复制代码
[root@webserver memcache-8.2]# phpize
Configuring for:
PHP Api Version:         20230831
Zend Module Api No:      20230831
Zend Extension Api No:   420230831
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.

[root@webserver memcache-8.2]# dnf install autoconf -y

[root@webserver memcache-8.2]# phpize
Configuring for:
PHP Api Version:         20230831
Zend Module Api No:      20230831
Zend Extension Api No:   420230831


[root@webserver memcache-8.2]# ./configure && make && make install
......
Build complete.
......

[root@webserver memcache-8.2]# ls
autom4te.cache  config.log     config.w32   libtool             memcache.php
build           config.m4      CREDITS      LICENSE             modules
config9.m4      config.nice    docker       Makefile            README
config.h        config.status  Dockerfile   Makefile.fragments  run-tests.php
config.h.in     configure      example.php  Makefile.objects    src
config.h.in~    configure.ac   include      memcache.la         tests


[root@webserver memcache-8.2]# cd /usr/local/php/
[root@webserver php]# ls
bin  etc  include  lib  php  sbin  var
[root@webserver php]# cd lib/
[root@webserver lib]# ls
php
[root@webserver lib]# cd php/
[root@webserver php]# ls
build  extensions
[root@webserver php]# cd extensions/
[root@webserver extensions]# ls
no-debug-non-zts-20230831
[root@webserver extensions]# cd no-debug-non-zts-20230831/
[root@webserver no-debug-non-zts-20230831]# ls
memcache.so  opcache.so


[root@webserver ~]# php -m
[PHP Modules]
bcmath
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gd
hash
iconv
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
random
Reflection
session
SimpleXML
soap
sockets
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

[root@webserver ~]# php -m | grep memcache
[root@webserver ~]#
bash 复制代码
[root@webserver ~]# systemctl restart php-fpm.service
[root@webserver ~]# php -m | grep memcache
memcache
bash 复制代码
[root@webserver ~]# dnf install memcached -y
[root@webserver ~]# systemctl enable --now memcached.service
Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service.
[root@webserver ~]# netstat -antlupe | grep memcache
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      986        419329     228330/memcached
tcp6       0      0 ::1:11211               :::*                    LISTEN      986        419330     228330/memcached



[root@webserver ~]# vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"	#将127.0.0.1改为0.0.0.0
复制代码
[root@webserver memcache-8.2]# cp example.php memcache.php /web/php/
[root@webserver memcache-8.2]# cd /web/php/
[root@webserver php]# ls
example.php  index.php  memcache.php

在浏览器中直接访问

我们发现打开memcache.php这个网页需要用户名和密码

复制代码
[root@webserver ~]# vim /web/php/memcache.php
......
define('ADMIN_USERNAME','admin');   // Admin Username
define('ADMIN_PASSWORD','vb');      // Admin Password
......
$MEMCACHE_SERVERS[] = '127.0.0.1:11211'; // add more as an array
......
复制代码
[root@webserver ~]# ab -n 1000 -c 500 php.vb.org/example.php
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking php.vb.org (be patient)
apr_sockaddr_info_get() for php.vb.org: Name or service not known (670002)
[root@webserver ~]# vim /etc/hosts
[root@webserver ~]# ab -n 1000 -c 500 php.vb.org/example.php
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking php.vb.org (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        BrandonX/
Server Hostname:        php.vb.org
Server Port:            80

Document Path:          /example.php
Document Length:        116 bytes

Concurrency Level:      500
Time taken for tests:   0.388 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      298000 bytes
HTML transferred:       116000 bytes
Requests per second:    2579.93 [#/sec] (mean)
Time per request:       193.804 [ms] (mean)
Time per request:       0.388 [ms] (mean, across all concurrent requests)
Transfer rate:          750.80 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    4   4.4      4      14
Processing:     9  139  51.5    170     186
Waiting:        2  139  51.5    170     186
Total:         16  143  47.8    170     193

Percentage of the requests served within a certain time (ms)
  50%    170
  66%    175
  75%    178
  80%    179
  90%    181
  95%    182
  98%    187
  99%    191
 100%    193 (longest request)

压测

复制代码
[root@webserver ~]# ab -n 1000 -c 500 php.vb.org/index.php
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking php.vb.org (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        nginx/1.26.3
Server Hostname:        php.vb.org
Server Port:            80

Document Path:          /index.php
Document Length:        74885 bytes

Concurrency Level:      500
Time taken for tests:   0.062 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      75092977 bytes
HTML transferred:       74885000 bytes
Requests per second:    16029.49 [#/sec] (mean)
Time per request:       31.193 [ms] (mean)
Time per request:       0.062 [ms] (mean, across all concurrent requests)
Transfer rate:          1175490.67 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    5   3.1      5      11
Processing:     1   19  11.5     17      42
Waiting:        0   12   8.6      6      37
Total:          2   24  11.5     22      44

Percentage of the requests served within a certain time (ms)
  50%     22
  66%     26
  75%     37
  80%     38
  90%     40
  95%     42
  98%     43
  99%     44
 100%     44 (longest request)

可以发现压测很快就完成了,并且压测结果显示没有失败传输的。

二次开发版本

bash 复制代码
[root@webserver ~]#./configure --prefix=/usr/local/openresty --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module  --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module  --with-pcre --with-stream  --with-stream_ssl_module  --with-stream_realip_module




[root@webserver ~]# vim .bash_profile

[root@webserver ~]# source .bash_profile

187

99% 191

100% 193 (longest request)

复制代码
[外链图片转存中...(img-Ije07BCY-1754927161622)]











[外链图片转存中...(img-NLGxHJUA-1754927161622)]



















压测

root@webserver \~\]# ab -n 1000 -c 500 php.vb.org/index.php This is ApacheBench, Version 2.3 \<$Revision: 1903618 $\> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking php.vb.org (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: nginx/1.26.3 Server Hostname: php.vb.org Server Port: 80 Document Path: /index.php Document Length: 74885 bytes Concurrency Level: 500 Time taken for tests: 0.062 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 75092977 bytes HTML transferred: 74885000 bytes Requests per second: 16029.49 \[#/sec\] (mean) Time per request: 31.193 \[ms\] (mean) Time per request: 0.062 \[ms\] (mean, across all concurrent requests) Transfer rate: 1175490.67 \[Kbytes/sec\] received Connection Times (ms) min mean\[+/-sd\] median max Connect: 0 5 3.1 5 11 Processing: 1 19 11.5 17 42 Waiting: 0 12 8.6 6 37 Total: 2 24 11.5 22 44 Percentage of the requests served within a certain time (ms) 50% 22 66% 26 75% 37 80% 38 90% 40 95% 42 98% 43 99% 44 100% 44 (longest request) 可以发现压测很快就完成了,并且压测结果显示没有失败传输的。 ### 二次开发版本 ```bash [root@webserver ~]#./configure --prefix=/usr/local/openresty --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module [root@webserver ~]# vim .bash_profile [root@webserver ~]# source .bash_profile \[外链图片转存中...(img-x7X56e8x-1754927161623)