企业级高性能Web服务器详解

一、Web服务基础介绍

1.1 web的访问流程

无特殊情况下单次的web服务访问流程图

  1. 用户发送请求:用户在浏览器中输入URL或点击链接,发送请求给服务器。
  2. DNS解析:浏览器根据URL中的域名进行DNS解析,获取域名对应的IP地址。
  3. 建立TCP连接:浏览器使用HTTP协议与服务器建立TCP连接。这个过程涉及TCP三次握手,确保双方建立起可靠的连接。
  4. 发起HTTP请求:浏览器向服务器发送HTTP请求。请求中包括请求行(请求方法,URL,HTTP协议版本等)、请求头部(包括User-Agent、Cookie等)和请求体(可选,如在上传文件时)。
  5. 服务器处理请求:服务器接收到请求后进行处理。处理的方式可以是查询数据库、执行业务逻辑处理等。服务器可能会生成动态内容或从文件系统中获取静态内容,并将处理结果返回给浏览器。
  6. 返回HTTP响应:服务器生成HTTP响应,包括响应行(HTTP协议版本,状态码等)、响应头部(包含响应数据类型、响应长度等)和响应内容(服务器返回的实际数据,如HTML文档、图片文件等)。
  7. 接收响应内容:浏览器接收到服务器返回的HTTP响应后,开始解析响应内容。根据响应头部中的Content-Type判断响应内容的类型。如果是HTML文档,则进行HTML解析,并下载显示其中的资源(如JavaScript、CSS等)。
  8. 渲染页面:浏览器根据HTML、CSS和JavaScript对响应内容进行解析和渲染。将网页内容呈现给用户,包括文本、图片、链接等。
  9. 断开TCP连接:当页面加载完毕后,浏览器和服务器断开TCP连接。这个过程使用了TCP四次挥手,确保双方安全关闭连接。

1.2 web的服务介绍

1.2.1 Apache 的经典Web服务端介绍

1.2.1.1 Apache prefork 模型结构图

  • 优点:稳定
  • 缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.2.1.2 Apache worker 模型结构图

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

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

1.2.2 Nginx-高性能的 Web 服务端

官网地址: www.nginx.org

nginx基本工作流程图:

1.3 I/O 模型

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

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

1.3.1 阻塞型 I/O 模型

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

1.3.2 非阻塞型 I/O 模型

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

1.3.3 多路复用 I/O

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。

1.3.4 信号驱动式 I/O 模型

信号驱动 I/O 的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知进程。
调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主程序可以继续向下执行,当有I/O 操作准备就绪 , 即内核数据就绪时,内核会为该进程产生一个 SIGIO 信号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据 , 将用户进程所需要的数据从内核空间拷贝到用户空间此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O ,并安装一个信号处理函数,进程继续运行并不阻塞
当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

1.3.5 异步 I/O 模型

异步 I/O 与 信号驱动 I/O 最大区别在于,信号驱动是内核通知用户进程何时开始一个 I/O 操作,而异步 I/O 是由内核通知用户进程I/O 操作何时完成,两者有本质区别 , 相当于不用去饭店场吃饭,直接点个外卖,把等待上菜的时间也给省了
相对于同步 I/O ,异步 I/O 不是顺序执行。用户进程进行 aio_read 系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket 数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO 两个阶段,进程都是非阻塞的。
信号驱动 IO 当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO 直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了

1.4 零拷贝

1.4.1 什么是零拷贝

零拷贝是解决传统Linux中I/O问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化。

1.4.2 零拷贝的相关技术

1、MMAP

  • mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问。
  • mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
  • 实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。
  • 内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输。

2、SENDFILE

3、DMA 辅助的SENDFILE

二、Nginx架构及安装

2.1 Nginx介绍及框架图

  • Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器。
  • Nginx官网:http://nginx.org

2.1.1 基础特性介绍

  • 模块化设计,较好的扩展性
  • 高可靠性
  • 支持热部署:不停机更新配置文件,升级版本,更换日志文件
  • 低内存消耗:10000keep-alive连接模式下的非活动连接,仅需2.5M内存(也可手动修改,使之内存更小)
  • event-driven,aio,mmapsendfile

2.1.2 与Web服务器相关的功能

  • 虚拟主机(server
  • 支持 keep-alive 和管道连接(利用一个连接做多次请求)
  • 访问日志(支持基于日志缓冲提高其性能)url rewirte
  • 路径别名
  • 基于IP及用户的访问控制
  • 支持速率限制及并发数限制
  • 重新配置和在线升级而无须中断客户的工作进程

2.1.3 master/worker进程的功能介绍

Master :

  • 对外接口:接收外部的操作(信号)
  • 对内转发:根据外部的操作的不同,通过信号管理 Worker
  • 监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
  • 读取Nginx 配置文件并验证其有效性和正确性
  • 建立、绑定和关闭socket连接
  • 按照配置生成、管理和结束工作进程
  • 接受外界指令,比如重启、升级及退出服务器等指令
  • 不中断服务,实现平滑升级,重启服务并应用新的配置
  • 开启日志文件,获取文件描述符
  • 不中断服务,实现平滑升级,升级失败进行回滚处理
  • 编译和处理perl脚本

Worker :

  • 所有 Worker 进程都是平等的
  • 实际处理:网络请求,由 Worker 进程处理
  • Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源
  • 增加上下文切换的损耗
  • 接受处理客户的请求
  • 将请求依次送入各个功能模块进行处理
  • I/O调用,获取响应数据
  • 与后端服务器通信,接收后端服务器的处理结果
  • 缓存数据,访问缓存索引,查询和调用缓存数据
  • 发送请求结果,响应客户的请求
  • 接收主程序指令,比如重启、升级和退出等

2.2 安装nignx

2.2.1 Nginx 编译安装

什么是编译器?

将高级语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成 .exe 程序;这个工具叫做编译器(Compiler)。

在编译安装Nginx时,我们需要依赖第三方软件库,这里会用到的有pcre(支持rewrite),zlib(支持gzip模块)和openssl(支持ssl模块)。

在安装前,先下载会用到的源码包,官方源码下载地址为:https://nginx.org/en/download.html

首先配置好虚拟机的硬件设施,根据自身电脑情况设定。

安装第三方库

[root@nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y

[root@nginx ~]# useradd -s /sbin/nologin -M nginx   #建立nginx用户

将下载好的源码包上传到/root,并解压

[root@nginx ~]# tar zxf nginx-1.24.0.tar.gz

添加解析文件并下载

[root@nginx 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_gzip_static_module \
>--with-http_stub_status_module \
>--with-pcre \
>--with-stream \
>--with-stream_ssl_module \
>--with-stream_realip_module

#\为换行符


查看nginx底下的目录

  • conf:保存nginx所有的配置文件,其中nginx.confnginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conffastcgi_params两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀去掉即可。
  • html:目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50xweb文件是默认的错误页面提示页面。
  • logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比
  • /var/logs/nginx里面。
  • sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。

启动Nginx

测试,检测nginx是否成功启动

查看nginx的大小

nginx关闭及重启

[root@nginx ~]# /usr/local/nginx/sbin/nginx -s stop

[root@nginx ~]# netstat -antlupe | grep nginx

[root@nginx ~]# /usr/local/nginx/sbin/nginx -s restart

[root@nginx sbin]# netstat -antlupe | grep nginx
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      0          68047      38977/nginx: master

关闭gcc

[root@nginx nginx-1.24.0]# vim auto/cc/gcc

验证版本及编译参数

重新加载shell配置

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

检查是否启动成功

测试

命令参数的使用及介绍

  • -v : show version and exit
  • -V : show version and configure options then exit #显示版本和编译参数
  • -t : test configuration and exit #测试配置文件是否异
  • -T : test configuration, dump it and exit #测试并打印
  • -p prefix : set prefix path (default: /etc/nginx/) # 指定 Nginx 目录
  • -c filename : set configuration file (default: /etc/nginx/nginx.conf) # 配置文件路径
  • -g directives : set global directives out of configuration file # 设置全局指令 , 注意和
    配置文件不要同时配置 , 否则冲突

配置文件第三行已经有指定参数,不能再指定了。

我们进入配置文件中,将指定的参数注释掉,再次执行 nginx -g "worker_processes 6;"就可以得到6个工作的worker进程了

注意:1、在指定参数时,不要忘记后面的分号

           2、指定时的参数必须是文件中没有的

2.2.2 nginx启动脚本的编写

nginx默认情况下没有启动文件,下面将介绍如何生成一个启动文件(脚本内容附后)

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target


[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true


[Install]
WantedBy=multi-user.target

重启

[root@nginx ~]# systemctl  daemon-reload
[root@nginx ~]# systemctl enable --now nginx.service
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.

[root@nginx ~]# ps aux | grep nginx
root       41779  0.0  0.1   9868  3204 ?        Ss   15:48   0:00 nginx: master process nginx
nginx      48678  0.0  0.5  17920  9076 ?        S    15:48   0:00 nginx: worker process
root       49018  0.0  0.1 221680  2304 pts/0    S+   15:48   0:00 grep --color=auto nginx

2.2.3 平滑升级和回滚

2.2.3.1 平滑升级
有时候我们需要对 Nginx 版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级。

案例:

1、上传源码包,并解压缩

2、编译并安装

[root@nginx nginx-1.26.1]#./configure --prefix=/usr/local/nginx 
>--user=nginx \
>--group=nginx  \
>--add-module=/root/echo-nginx-module-0.63 \
>--with-http_ssl_module \
>--with-http_v2_module \
>--with-http_realip_module \
>--with-http_gzip_static_module \
>--with-http_stub_status_module \
>--with-pcre \
>--with-stream \
>--with-stream_ssl_module \
>--with-stream_realip_module

3、查看两个版本

4、备份之前的旧版nginx命令

[root@nginx nginx-1.24.0]# cd /usr/local/nginx/

[root@nginx nginx]# cd sbin/

[root@nginx sbin]# ls 

nginx

[root@nginx sbin]# cp nginx nginx.old

[root@nginx sbin]# ls 

nginx  nginx.old

5、把新版本的nginx命令复制过去

[root@nginx sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/

6、检测一下是否有问题

7、查看是否复制成功

8、升级

首先查看进程,正常情况下,会有一个master进程、一个worker进程,同时记住进程号,便于接下来的操作。USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名nginx.pid.oldbin,并启动新的nginx,此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80,此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。

9、测试,平滑升级后,我们使用的nginx版本会从原来的1.24.0变成1.26.1

2.3.1.2 回滚

1、我们平滑升级后的版本如果出现了问题,这时可以进行回滚操作,重新拉回进版本的worker。首先将新版本的nginx命令进行复制并进行查看

2、执行回滚操作

3、查看版本信息,回滚完成

三、Nginx核心配置详解

3.1 配置文件说明

nginx 官方帮助文档网址: http://nginx.org/en/docs/

3.1.1 Nginx的配置文件的组成部分:

  • 主配置文件:nginx.conf
  • 子配置文件: include conf.d/*.conf
  • fastcgi uwsgiscgi 等协议相关的配置文件
  • mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮
  • 件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某
  • 种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动
  • 使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

注意:

  • 使用#符号添加注释,提高可读性
  • 使用$符号使用变量
  • 可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐
  • 每条指令以;分号结尾,指令与值之间以空格符号分隔
  • 可以将多条指令放在同一行,用分号分隔即x可,但可读性差,不推荐

3.1.2 主配置文件结构

main block :主配置段,即全局配置段,对 http, mail 都有效
# 事件驱动相关的配置
event {
   ...
}
主要影响 nginx服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型 处理请求,每个工作进程可以同时支持的 最大连接数,是否开启对多工作进程下的网络连接进行序列化等。
#http/https 协议相关配置段
http {
    ...
}
http 块是 Nginx 服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都 # 可以在这设置, http 块可以包含多个server 块,而一个 server 块中又可以包含多个 location 块,server块可以配置文件引入、 MIME-Type 定义、日志自定义、是 否启用sendfile 、连接超时时间和 单个链接的请求上限等。
# 默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
   ...
}
和邮件相关的配置
#stream 服务器相关配置段
stream {
   ...
}
tcp 代理配置, 1.9 版本以上支持

3.1.3 相关参数解释

参数解释
worker_processes 1
启动的工作进程数数量,可手动修改
worker_connections 1024
设置单个 nginx 工作进程可以接受的最大并发连接数量
listen 80
配置 server 监听的端口
index index.html index.htm
默认的页面文件名称
keepalive_timeout 65
长连接超时时间,单位是秒
root html
相当于默认页面的目录名称,默认是安装目录的相对路径,可以使 用绝对路径配置。

3.2 nginx全局配置及参数优化调整

3.2.1全局配置

3.2.1.1 查看指定用户并修改为nginx
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
####
user  nginx;
worker_processes  auto;
###

#重启并查看进程
[root@nginx ~]# nginx -s reload
[root@nginx ~]# ps aux | grep nginx
root       38977  0.0  0.1   9864  3204 ?        Ss   21:37   0:00 nginx: master process ./nginx
nginx      45134  0.0  0.2  14240  5264 ?        S    22:04   0:00 nginx: worker process
nginx      45170  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45171  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45172  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45173  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
root       45175  0.0  0.1 221812  2304 pts/0    S+   22:20   0:00 grep --color=auto nginx

3.2.2.2 如何将nginx工作进程绑定到CPU核心(此处以四核心为例)
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
####
worker_cpu_affinity 0001 0010  0100  1000;
####

[root@nginx ~]# ps aux | grep nginx
root       38977  0.0  0.1   9864  3204 ?        Ss   21:37   0:00 nginx: master process ./nginx
nginx      45134  0.0  0.2  14240  5264 ?        S    22:04   0:00 nginx: worker process
nginx      45170  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45171  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45172  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
nginx      45173  0.0  0.2  14212  5108 ?        S    22:20   0:00 nginx: worker process
root       45179  0.0  0.1 221812  2304 pts/0    S+   22:22   0:00 grep --color=auto nginx
3.2.2.3 实现nginx的高并发配置

1、修改当前系统可打开的最大文件数为10000

2、修改配置文件

[root@nginx ~]# vim /etc/security/limits.conf

*    -   noproc          100000

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf

3、安装httpd

[root@nginx ~]# yum install httpd -y

4、访问

当链接数值给的过大,就会出现太满溢出的情况。压力过大时,访问速度也会减慢。

3.2.2 在nginx中自定义站点

1、定义子配置文件的路径

注意:要写到前面,写到后面不生效

[root@nginx ~]#  vim /usr/local/nginx/conf/nginx.conf

2、创建虚拟主机网络配置

[root@nginx ~]# mkdir -p /usr/local/nginx/conf.d
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
}

[root@nginx ~]# mkdir -p /data/web/html

3、导入

[root@nginx ~]# echo www.yee.org > /data/web/html/index.html

4、检验并刷新

5、在本地文件中做解析

点击编辑将权限全部打开

修改完成后,点击确定,单击右键,选择在记事本中编辑,输入以下内容

6、访问

3.2.3 nginx中的root和alias

root示例:

指定web的家目录,在定义location时,文件的绝对路径等于root+location

#修改配置文件
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    location /test1/  {
        root /data/web;
    }
}


#建立文件并写入
[root@nginx ~]# mkdir /data/web/test1 -p
[root@nginx ~]#  echo www.yee.org  >  /data/web/html/index.html


#检测是否有问题
[root@nginx ~]# 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 ~]# nginx -s reload

测试

alias示例:

[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    location /test1/ {
        root /data/web;
    }

# 在脚本中添加alias
    location /test2 {
        alias /data/web/test1;
    }
}

测试:

此时访问www.yee.org,页面出现test1

3.2.4 nginx-location 用法详解

3.2.4.1 语法规则
语法解释
=
用于标准 uri 前,需要请求字串与 uri 精确匹配,大小敏感, 如果匹配成功就停止向下匹配并立即处理请求
^~
于标准 uri 前,表示包含正则表达式 , 并且匹配以指定的正则表达式开头
uri 的最左边部分做匹配检查,不区分字符大小写
~
用于标准 uri 前,表示包含正则表达式 , 并且区分大小写
~*
用于标准 uri 前,表示包含正则表达式 , 并且不区分大写
\
用于标准 uri 前,表示包含正则表达式并且转义字符。可以将 . * ? 等转义为普通符号
!~ 和 !~*如果有多个location的正则能匹配的话,则使用正则表达式最长的那个
没有前缀
匹配起始于此 uri 的所有的 uri
@定义一个命名的 location,使用在内部定向时,例如 error_page, try_files
3.2.4.2 案例
  • 在一个serverlocation配置段可存在多个,用于实现从uri到文件系统的路径映射;
  • ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri
  • uri是用户请求的字符串,即域名后面的web文件路径
  • 然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# 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 ~]# nginx -s reload
[root@nginx ~]# mkdir -p /data/web{1..5}
[root@nginx ~]# mkdir -p /data/web{1..5}/test
[root@nginx ~]# echo web1 > /data/web1/test/index.html
[root@nginx ~]# echo web2 > /data/web2/test/index.html
[root@nginx ~]# echo web3 > /data/web3/test/index.html
[root@nginx ~]# echo web4 > /data/web4/test/index.html
[root@nginx ~]# echo web5 > /data/web5/test/index.html
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    location /test {
        root /data/web1;
    }

    location = test  {
        root /data/web2;
    }

    location ^~ /t {
        root /data/web3;
    }

    location ~ .html$ {
        root /data/web4;
    }

    location ~*.HTML$ {
        root /data/web5;
    }
}

测试

优先级:

location 优先级: (location =) > (location ^~ 路径 ) > (location ~,~* 正则顺序 ) >
(location 完整路径 ) > (location 部分起始路径 ) > (/)
在语法规则都存在的情况下,测试时会访问优先级更高的,在优先级不分先后时,按照出场顺序先后被访问

3.2.5 Nginx 用户认证

[root@nginx ~]# htpasswd -cm /usr/local/nginx/conf/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx ~]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$t6NeKY0E$BEfpNCpajusmcg8gx8Zft0
[root@nginx ~]# htpasswd -m /usr/local/nginx/conf/.htpasswd yee
New password:
Re-type new password:
Adding password for user yee
[root@nginx ~]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$t6NeKY0E$BEfpNCpajusmcg8gx8Zft0
lee:$apr1$6dVWEaTe$b3DxsQs.zXLc4Qhiu3u4e1
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# echo yee > /data/web/yee/index.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;

    location /yee {
         root /data/web;
         auth_basic "login password  !!";
         auth_basic_user_file "/usr/local/nginx/.htpasswd";
}

}
[root@nginx ~]# nginx -s reload



测试

3.2.6 自定义错误页面

[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    error_page 404   /40x.html;

    location /yee {
         root /data/web;
         auth_basic "login password  !!";
         auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }

    location = /40x.html{
         root  /data/web/errorpage;
    }
}

[root@nginx ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx ~]# mkdir -p /data/web/errorpage
[root@nginx ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx ~]# nginx -s reload

3.2.7 nginx中的文件检测

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

在配置文件中添加以下内容,并访问

[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat  /usr/local/nginx/conf.d/vhosts.conf
server {
    listen 80;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    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 /yee {
         root /data/web;
         auth_basic "login password  !!";
         auth_basic_user_file "/usr/local/nginx/.htpasswd";
    }

    location = /40x.html{
         root  /data/web/errorpage;
    }
}


测试:
[root@nginx ~]# mkdir /data/web/html/error
[root@nginx ~]# curl www.yee.org
www.yee.org
[root@nginx ~]# rm -fr /data/web/html/error/
[root@nginx ~]# curl www.yee.org
www.yee.org
[root@nginx ~]# rm -fr /data/web/html/index.html
[root@nginx ~]# curl www.yee.org
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.26.1</center>
</body>
</html>


[root@nginx ~]# mkdir /data/web/html/error
[root@nginx ~]# echo error default > /data/web/error/index.html


3.2.8 nginx中的长链接管理

keepalive_requests 3;
keepalive_timeout 65 60;
开启长连接后,返回客户端的会话保持时间为60s ,单次长连接累计请求达到指定次数请求或 65 秒就会被断开,第二个数字60 为发送给客户端应答报文头部中显示的超时时间设置 60s: 如不设置客户端将不显示超时时间。
Keep-Alive:timeout=60    # 浏览器收到的服务器返回的报文
                                        #如果设置为0表示关闭会话保持功能,将如下显示:
                                        #Connection:close 浏览器收到的服务器返回的报文

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf   #修改内容如下图
[root@nginx ~]# dnf install telnet -y  #安装长链接测试工具

测试:

 

四、Nginx 的高级用法

4.1 nginx的状态页面

  • 基于nginx 模块 ngx_http_stub_status_module 实现,
  • 在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
  • 否则配置完成之后监测会是提示法错误

注意:

状态页显示的是整个服务器的状态,而非虚拟主机的状态

参数解释
Active connections
当前处于活动状态的客户端连接数
包括连接等待空闲连接数 =reading+writing+waiting
accepts
统计总值, Nginx 自启动后已经接受的客户端请求连接的总数
handled
统计总值, Nginx 自启动后已经处理完成的客户端请求连接总数
通常等于 accepts ,除非有因 worker_connections 限制等被拒绝的连接
requests
统计总值, Nginx 自启动后客户端发来的总的请求数
Reading
当前状态,正在读取客户端请求报文首部的连接的连接数
数值越大 , 说明排队现象严重 , 性能不足
Writing
当前状态,正在向客户端发送响应报文过程中的连接数 , 数值越大 , 说明访问量很大
Waiting
当前状态,正在等待客户端发出请求的空闲连接数
开启 keep-alive 的情况下 , 这个值等于 active – (reading+writing)

配置:
[root@nginx ~]# cd /usr/local/nginx/conf.d/
[root@nginx conf.d]# vim status.conf
[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# vim /etc/hosts
[root@nginx conf.d]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.200  nginx.node   www.ye.org   status.yee.org
[root@nginx conf.d]# cat status.conf
server {
     listen 80;
     server_name status.yee.org;
     root  /data/web/html;
     index  index.html;

     location /status  {
           stub_status;
          #auth_basic "auth login";
          #auth_basic_user_file /apps/nginx/conf/.htpasswd;
           allow 172.25.254.200/24;
           allow 127.0.0.1;
           deny all;
   }

}

测试:
[root@nginx conf.d]# curl status.yee.org
Active connections:1
server accepts handled requests
36 36  67
Reading:0 Writing:1 Waiting:0


4.2 nginx的数据压缩功能

  • Nginx在传输数据较大的文件时,传输速度较慢,此时我们可以对指定文件进行压缩后再传输给客户端,在压缩过程中还可以设置比例压缩,压缩后的文件大小将比源文件显著变小,这样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相应的CPU资源。
  • Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module,默认是内置模块
参数解释
gzip on | off
启用或禁用 gzip 压缩,默认关闭
gzip_comp_level n
n=1~9,默认为 1 ,值越高压缩后文件越小,但是消耗 cpu 比较高。基本设定未 4 或者 5
gzip_disable "MSIE [1-6]\."
禁用 IE6 gzip 功能,早期的 IE6 之前的版本不支持压缩
gzip_min_length 1k
gzip 压缩的最小文件,小于设置值的文件将不会压缩
gzip_http_version 1.0 | 1.1
启用压缩功能时,协议的最小版本,默认 HTTP/1.1
gzip_buffers number size
指定 Nginx 服务需要向服务器申请的缓存空间的个数和大小 , 平台不同 , 默认 :32 4k 或者 16 8k
gzip_types mime-type ...
指明仅对哪些类型的资源执行压缩操作 ; 默认为 gzip_types text/html ,不用显示指定,否则出错
gzip_vary on | off
如果启用压缩,是否在响应报文首部插入 “Vary: Accept-Encoding”, 一般建议打开
gzip_static on | off
预压缩,即直接从磁盘找到对应文件的 gz 后缀的式的压缩文件返回给用户,无需消耗服务器 CPU
[root@nginx conf.d]# cd ..
[root@nginx nginx]# ls
conf  conf.d  html  logs  sbin
[root@nginx nginx]# cd conf
[root@nginx nginx]# vim /usr/local/nginx/conf/nginx.conf
######
    gzip  on;  # 取消注释,开启压缩功能
    gzip_comp_level 5;  #设置压缩等级为5
    gzip_min_length 1k;   #文件小于1k的不压缩
    gzip_http_version 1.1;  #http默认版本
    gzip_vary on;   #启用压缩
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/gif image/png;   #指明将要进行压缩的文件 

#########

[root@nginx conf]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx conf]# nginx -s reload


测试:
[root@nginx conf]# echo xixixixixi > /data/web/html/small.html
[root@nginx conf]# du -sh /usr/local/nginx/logs/
access.log   error.log   nginx.log
[root@nginx conf]# du -sh /usr/local/nginx/logs/access.log
3.1M   /usr/local/nginx/logs/access.log
[root@nginx conf]# cat /usr/local/nginx/logs/access.log  > /data/web/html/big.html
[root@nginx conf]# curl --head --compressed 172.25.254.200/small.html
HTTP/1.1 200 ok
Server: nginx/1.26.1
Date: Wed, 21 Aug 2024 20:11:50 GMT
Content-Type: text/html
Content-Length: 18
Last-Modified:Fri,21 Aug2024 20:10:30 GMT
Connection: keep-alive
Keep-Alive:timeout=60
SerVer0G70XETag:"66bf0976-10"
Accept-Ranges:bytes


#因为报文太长,所以在查看的时候只查看头部  即--head
[root@nginx conf]# curl --head --compressed 172.25.254.200/big.html
HTTP/1.1 200 ok
Server: nginx/1.26.1
Date: Wed, 21 Aug 2024 20:12:10 GMT
Content-Type: text/html
Last-Modified:Fri,21 Aug2024 20:11:21 GMT
Connection: keep-alive
Keep-Alive:timeout=60
SerVer0G70XETag:"66bf0976-zfa98f"
Accept-Ranges:gzip   #被压缩了

4.3 nginx中的变量详解

  • nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
  • 变量可以分为内置变量和自定义变量
  • 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值
  • 官方文档:http://nginx.org/en/docs/varindex.html

[root@nginx ~]# cd /usr/local/nginx/
[root@nginx nginx]# ls
[root@nginx nginx]# cd conf.d/
[root@nginx conf.d]# vim vars.conf
[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# 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 conf.d]# cat vars.conf
server {
    listen 80;
    server_name var.yee.org;
    root /data/web/html;
    index index.html;

    location  /var {
        default_type test/html;
        echo "yee.org";

    }
}


# 测试:
[root@nginx conf.d]# curl var.yee.org/var
yee.org


[root@nginx conf.d]# vim vars.conf
[root@nginx conf.d]# cat vars.conf
server {
    listen 80;
    server_name var.yee.org;
    root /data/web/html;
    index index.html;

    location  /var {
       echo $remote_addr;
        echo $args;
        echo $is_args;
        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_key2;
        echo $http_cookie;
        echo $cookie_key2;
        echo $yee;

    }
}

[root@nginx conf.d]# curl var.yee.org/var?name=yee&&id=6666
172.25.254.200
name=yee
?
/data/web/html
/var
var.yee.org
34728
GET
/data/web/html/var
/var?name=yee
http
HTTP/1.1
172.25.254.200
var.yee.org
80
curl/7.76.1
key1=yee.key2=yee1
yee1
yee






五、Nginx Rewrite 相关功能

  • Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
  • 此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE
  • rewritenginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
  • 比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
  • 另外还可以在一定程度上提高网站的安全性。
  • 官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

5.1 rewrite_module 模块指令

5.1.1 if判定

用于条件匹配判断,并根据条件判断结果选择不同的 Nginx 配置,可以配置在 server location 块中进行配置,Nginx if 语法仅能使用 if 做单次判断,不支持使用 if else 或者 if elif 这样的多重判断。
符号链接
符号解释
=
比较变量和字符串是否相等,相等时 if 指令认为该条件为 true ,反之为 false
!=
比较变量和字符串是否不相等,不相等时 if 指令认为条件为 true ,反之为 false
~
区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~
区分大小写字符 , 判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~*
不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~*
不区分大小字符 , 判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f     /    !-f
判断请求的文件是否存在和是否不存在
-d    /    !-d
判断请求的目录是否存在和是否不存在

-x    /    !-x

判断文件是否可执行和是否不可执行
-e    /    !-e
判断请求的文件或目录是否存在和是否不存在 ( 包括文件,目录,软链接 )

示例:

[root@nginx conf.d]# vim vars.conf
server {
    listen 80;
    server_name var.yee.org;
    root /data/web/html;
    index index.html;

    location  /var {
        default_type test/html;
        echo $remote_addr;
        echo $args;
        echo $is_args;
        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_key2;

    }
#### 增添以下内容

    location /test2 {
    if ( !-e $request_filename ){
       echo "$request_filename is not exist";
       }
   }
}

#测试
#文件存在的话
[root@nginx conf.d]# mkdir -p  /data/web/html/test2
[root@nginx conf.d]# echo test2 > /data/web/html/test2/index.html
[root@nginx conf.d]# curl var.yee.org/test2/index.html
test2

#文件不存在的话
[root@nginx conf.d]# rm -fr /data/web/html/test2/index.html
[root@nginx conf.d]# curl var.yee.org/test2/index.html
/data/web/html/test2/index.html is not exist



5.1.2 break

[root@nginx conf.d]# vim vars.conf
#####增添代码#####
 location /break {
        default_type text/html;
        set $name yee;
        echo $name;
        set $id 666;
        echo $id;
    }
#################

#重启
[root@nginx conf.d]# nginx -s reload

#测试
[root@nginx conf.d]# curl var.yee.org/break
yee
666

5.1.3 return

[root@nginx conf.d]# vim vars.conf
#####增加代码#######
 location /return {
        default_type text/html;
        if ( !-e $request_filename){
            return 301 http://www.baidu.com;
        }
        echo "$request_filename is exist";
    }
####################


# 重启
[root@nginx conf.d]# nginx -s reload


# 检测
[root@nginx conf.d]# curl -I var.yee.org/return
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.2
Date: Sun, 21 Aug 2024 03:01:30 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.baidu.com


[root@nginx conf.d]# mkdir  -p /data/web/html/return
[root@nginx conf.d]# curl -I var.yee.org/return
HTTP/1.1 200 OK
Server: nginx/1.26.2
Date: Sun, 21 Aug 2024 03:01:58 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding



5.2 rewrite 指令

5.2.1 rewrite相关介绍

  • 通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理
  • 官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
  • 语法格式 :rewrite regex replacement [flag];

正表达式格式:

.                                             #匹配除换行符以外的任意字符
\w                                           #匹配字母或数字或下划线或汉字
\s                                            #匹配任意的空白符
\d                                            #匹配数字
\b                                            #匹配单词的开始或结束
^                                             #匹配字付串的开始
$                                             #匹配字符串的结束
*                                             #匹配重复零次或更多次
+                                            #匹配重复一次或更多次
?                                            #匹配重复零次或一次
(n)                                          #匹配重复n次
{n,}                                         #匹配重复n次或更多次
{n,m}                                      #匹配重复n到m次
*?                                           #匹配重复任意次,但尽可能少重复
+?                                           #匹配重复1次或更多次,但尽可能少重复
??                                           #匹配重复0次或1次,但尽可能少重复
{n,m}?                                     #匹配重复n到m 次,但尽可能少重复
{n,}?                                        #匹配重复n次以上,但尽可能少重复
\W                                           #匹配任意不是字母,数字,下划线,汉字的字符
\S                                            #匹配任意不是空白符的字符
\D                                            #匹配任意非数字的字符
\B                                             #匹配不是单词开头或结束的位置
flag说明
参数解释
redirect
临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新 URL 给客户端
由客户端重新发起请求 ; 使用相对路径 , 或者 http:// https:// 开头,状态码: 302
permanent
重写完成后以永久重定向方式直接返回重写后生成的新 URL 给客户端
由客户端重新发起请求,状态码: 301
break
重写完成后 , 停止对当前 URL 在当前 location 中后续的其它重写操作
而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在 location 中使用
适用于一个 URL 一次重写
last
重写完成后 , 停止对当前 URI 在当前 location 中后续的其它重写操作,
而后对新的 URL 启动新一轮重写检查,不建议在 location 中使用
适用于一个 URL 多次重写,要注意避免出现超过十次以及 URL 重写后返回错误的给用户

5.2.2永久与临时重定向

[root@nginx conf.d]# vim vars.conf
################
     location / {
        root /data/web/var;
        index index.html;
        rewrite / http://www.yee.com permanent;
        #rewrite / http://www.yee.com redirect;
    }
################

[root@nginx conf.d]# mkdir /data/web/var -p
[root@nginx conf.d]# echo var page > /data/web/var/index.html
[root@nginx conf.d]# nginx -s reload

#测试:
[root@nginx conf.d]# curl www.yee.org  # curl不支持重对象
var.yee.org
[root@nginx conf.d]# curl -I var.yee.org
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Thu, 21 Aug 2024 07:33:08 GMT
Content-Type: text/html
Content-Length: 128
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.yee.com

5.2.3 break 和 last

建立实验素材

[root@nginx conf.d]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx conf.d]# echo test1 > /data/web/html/test1/index.html
[root@nginx conf.d]# echo test2 > /data/web/html/test2/index.html
[root@nginx conf.d]# echo last > /data/web/html/last/index.html
[root@nginx conf.d]# echo break > /data/web/html/break/index.html

编写脚本:

[root@nginx conf.d]# vim vars.conf
################
server {
    listen 80;
    server_name var.yee.org;
    root /data/web/html;
    index index.html;

    location /break {
        rewrite ^/break/(.*) /test1/$1;
        rewrite ^/test1/(.*) /test2/$1;
    }

    location /last {
        rewrite ^/break/(.*) /test1/$1;
        rewrite ^/test1/(.*) /test2/$1;
    }

    location /test1 {
        default_type test/html;
        echo "yee hahahahahaha";
    }

    location /test2 {
        root /data/web/html;
################
[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# curl -I var.yee.org/break
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.1
Date: Thu, 22 Aug 2024 07:55:17 GMT
Content-Type: text/html
Content-Length: 169
Location: http://var.yee.org/break/
Connection: keep-alive

5.2.4 搭建https

#搭建https服务

[root@nginx nginx]# mkdir certs
[root@nginx nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/yee.org.key -x509 -days 365 -out /usr/local/nginx/certs/yee.org.
..........+.+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+......+.+...+...........+....+......+......+..+.+..+.......+..+....+............+...+.....+......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+...........+...+..........+..+.+.....+..................+................+...+..+.........+.+...+...+..+......+.+..............+.......+...+..+....+...+..+......+..........+...+.....+....+..+.+..+...+.........+......+.......+.....+.+.....+.+...+............+...........+.........+.+.....+....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+...........+.+.....+...................+..............+......+.............+.....+...+...................+.....+.+..................+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:yee
Organizational Unit Name (eg, section) []:webserver
Common Name (eg, your name or your server's hostname) []:www.yee.org
Email Address []:admin@yee.org

#查看是否建立成功
[root@nginx nginx]# cd /usr/local/nginx/certs/
[root@nginx certs]# ls
yee.org.  yee.org.key


#编写脚本

[root@nginx nginx]# cd conf.d/
[root@nginx conf.d]# vim vhosts.conf
[root@nginx conf.d]# cat vhosts.conf
server {
    listen 80;
    listen 443 ssl;
    server_name www.yee.org;
    root /data/web/html;
    index index.html;
    ssl_certificate /usr/local/nginx/certs/yee.org.crt;
    ssl_certificate_key /usr/local/nginx/certs/yee.org.key;
    ssl_session_cache   shared:SSL:1m;
    ssl_session_timeout   5m;

  location / {
        if ( $scheme = http ){
             rewrite  / https://#$host redirect;
        }
     }

}

#重启
[root@nginx conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx conf.d]# nginx -s reload


测试:

[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# curl -KL www.yee.org
www.yee.org

5.3 防盗链

案例:

上传两张图片,注意不要放在同一目录下!

[root@nginx ~]# mkdir /data/web/html/images

测试:

新建虚拟机并安装:

[root@client ~]# cat /var/www/html/index.html
<html>

  <head>
      <meta http-equiv=Content-Type content="text/html,charset=utf-8">
      <title>盜链//title>
</head>

 <body>
    <img src="http://w.lee.org/images/lee.png">
    <h1 style="color:red">欢迎大家</h1>
    <p><a href=http://w.lee.org>hhhhhh</a>dddd</p>
</body>

<html>

测试:

六 、Nginx反向代理

反向代理: reverse proxy ,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。

6.1 模块解释说明

模块

说明

ngx_http_proxy_module
将客户端的请求以 http 协议转发至指定服务器进行处理
ngx_http_upstream_module
用于定义为 proxy_pass,fastcgi_pass,uwsgi_pass
等指令引用的后端服务器分组
ngx_stream_proxy_module
将客户端的请求以 tcp 协议转发至指定服务器处理
ngx_http_fastcgi_module
将客户端对 php 的请求以 fastcgi 协议转发至指定服务器助理
ngx_http_uwsgi_module
将客户端对 Python 的请求以 uwsgi 协议转发至指定服务器处理

6.2 逻辑调用关系及访问逻辑图

调用:

访问:

  • 同构代理:用户不需要其他程序的参与,直接通过http协议或者tcp协议访问后端服务器
  • 异构代理:用户访问的资源时需要经过处理后才能返回的,比如phppython,等等,这种访问资源需要经过处理才能被访问

6.3 http反向代理

6.3.1 反向代理配置参数说明

  • proxy_pass:用来设置将客户端请求转发给的后端服务器的主机 可以是主机名(将转发至后端服务做为主机头首部)IP地址:端口的方式 也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持。
  • proxy_hide_header field :用于nginx作为反向代理的时候,在返回给客户端http响应时隐藏后端服务器相应头部的信息,可以设置在http,serverlocation块。
  • proxy_pass_header field:透传      默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数 ,如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端 ,field 首部字段大小不敏感。
  • proxy_pass_request_body on | off:是否向后端服务器发送HTTP实体部分,可以设置在http,serverlocation块,默认即为开启。
  • proxy_pass_request_headers on | off:是否将客户端的请求头部转发给后端服务器,可以设置在http,serverlocation块,默认即为开启。
  • proxy_set_header:可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部。
  • proxy_connect_timeout time:配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒。
  • 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

6.3.2 案例

6.3.2.1 http反向负载均衡
#在web1和web2上安装httpd并启动
[root@web20 ~]# yum install httpd -y
[root@web20 ~]# echo 172.25.254.20 > /var/www/html/index.html
[root@web20 ~]# systemctl enable --now httpd
[root@web20 ~]# mkdir -p /var/www/html/static
[root@web20 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html


[root@web10 ~]# yum install httpd -y
[root@web10 ~]# echo  172.25.254.10 > /var/www/html/index.html
[root@web10 ~]# systemctl enable --now http


#编写脚本
[root@nginx ~]# vim /apps/nginx/conf/conf.d/pc.conf
[root@nginx ~]# cat /apps/nginx/conf/conf.d/pc.conf
upstream webserver {
#ip_hash;
#hash $request_uri consistent;
#hash $cookie_lee
#least_conn;
server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;
server 172.25.254.10:80 weight=1 fail_timeout=15s max_fails=3;
server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.lee.org;
location ~ / {
proxy_pass http://webserver;
}
}


#重启
[root@nginx ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@nginx ~]# nginx -s reload


测试:

[root@nginx ~]# curl www.yee.org
172.25.254.10

[root@nginx ~]# curl www.yee.org/static
172.25.254.20

6.3.2.2 四层负载均衡
#在web20中安装mysql
[root@web20 ~]# yum install mariadb-server -y
[root@web20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=20
[root@web20 ~]# systemctl start mariadb
[root@web20 ~]# mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
[root@web10 ~]# mysql -ulee -plee -h172.25.254.20 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+


#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@nginx ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
[root@nginx ~]# mysql -ulee -plee -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 30 |
+-------------+

6.4 实现FastCGI

6.4.1 FastCGI配置指令解释

配置指令解释
fastcgi_pass address:port
转发请求到后端服务器, address 为后端的 fastcgi server 的地址,可用位置: location, if in locatio
fastcgi_index name
fastcgi 默认的主页资源,示例: fastcgi_index index.php
fastcgi_param parameter value [if_not_empty]
设置传递给 FastCGI 服务器的参数值,可以是文本,变量或组合,可用于将 Nginx 的内置变量赋值给自定义key
fastcgi_param REMOTE_ADDR  $remote_addr;
客户端IP
fastcgi_param REMOTE_PORT   $server_port
客户端源端口
fastcgi_param SERVER_ADDR   $server_addr

请求的服务器IP地址

fastcgi_param SERVER_PORT    $server_port
请求的服务器端口
fastcgi_param SERVER_NAME   $server_name
请求的server name

6.4.2 案例:Nginxphp-fpm在同一服务器

6.4.2.1 编译安装nginx

上传

解压

编译

启动

[root@nginx nginx-1.26.1]# systemctl start nginx
[root@nginx nginx-1.26.1]# ps aux | grep ngin
root       56741  0.0  0.1   9916  2052 ?        Ss   10:56   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx      56742  0.0  0.4  17968  8708 ?        S    10:56   0:00 nginx: worker process
nginx      56743  0.0  0.4  17968  8708 ?        S    10:56   0:00 nginx: worker process
nginx      56744  0.0  0.4  17968  8708 ?        S    10:56   0:00 nginx: worker process
nginx      56745  0.0  0.4  17968  8580 ?        S    10:56   0:00 nginx: worker process
root       56747  0.0  0.1 221680  2304 pts/0    S+   10:57   0:00 grep --color=auto ngin

6.4.2.2 编译安装php

上传解压并编译安装php

# 利用yum解决php依赖
[root@nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel
libpng-devel libcurl-devel oniguruma-devel

# 编译安装
[root@Nginx ~]# ./configure \
--prefix=/usr/local/php \ #安装路径
--with-config-file-path=/usr/local/php/etc \ #指定配置路径
--enable-fpm \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cgi

安装阿里云镜像软件包

php相关优化配置

生成主配置文件并修改时区

[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 etc]# cd /root/php-8.3.9/
[root@nginx php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
[root@nginx php-8.3.9]# vim sapi/fpm/php-fpm.service /lib/systemd/system/

准备php测试页面

[root@nginx php]# vim index.php
[root@nginx php]# cat index.php
<?php
phpinfo();
?>

Nginx配置转发

[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

测试

添加php环境变量

上传mencache文件并解压和编译安装

[root@nginx~]#tar zxf memcache-8.2.tgz
[root@nginx~]#cdmemcache-8.2/
[root@nginxmemcache-8.2]#phpize
[root@nginxmemcache-8.2]#./configure && make && makeinstall

#启动该服务
[root@nginx ~]# systemctl start memcached.service

将以下两个文件放在同一目录下,否则不生效

[root@nginx lib]# cp /usr/local/php/etc/php.ini  /usr/local/php/lib/php.ini
[root@nginx lib]# ls
php php.ini

再次测试

6.4.3 php高速缓存

在进行高速缓存实验时,我们需要将nginx重新编译安装,操作如下:

[root@nginx ~]# rm -fr /usr/local/nginx/
[root@nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@nginx ~]# cd nginx-1.26.1/
[root@nginx nginx-1.26.1]# ./configure --prefix=/apps/nginx --user=nginx --
group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_realip_module --with-http_stub_status_module --with-http_gzip_static_module
--with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --
add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-
0.33
[root@nginx nginx-1.26.1]# make && make install
[root@nginx ~]# vim /usr/local/nginx/conf.d/php.conf
upstream memcache {
    server 127.0.0.1:11211;
    keepalive 512;
}

server {
  listen 80;
  server_name php.yee.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;
}

    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;
    }
}
[root@nginx ~]# systemctl start nginx

测试

[root@nginx ~]# ab -n500 -c10 http://php.yee.org/index.php
Concurrency Level: 10
Time taken for tests: 0.255 seconds
Complete requests: 500
Failed requests: 0

七、nginx的二次版本开发

7.1 什么是openresty?

OpenResty(也称为 ngx_openresty)是一个全功能的 Web 应用服务器。它打包了标准的 Nginx 核心,很多常用的第三方模块,以及它们的大多数依赖项。

通过糅合众多设计良好的 Nginx 模块,OpenResty 有效地把 Nginx 服务器转变为一个强大的 Web 应用服务器,基于它开发人员可以使用 Lua 编程语言对 Nginx 核心以及现有的各种 Nginx C 模块进行脚本编程,构建出单机可以处理 10K 以上并发请求的极端高性能的 Web 应用。

官网地址为 : http://openresty.org/cn/

7.2 编译安装openresty

上传openresty软件包并解压缩

测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值