高性能web服务器Nginx

一、网络服务

网络影响用户体验的因素

1.客户端

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

2.服务器

  • 服务端网络速率
  • 服务端硬件配置
  • 服务端架构设计
  • 服务端应用程序工作模式
  • 服务端并发数量服务端响应文件大小及数量buffercache
  • 服务端I/O压力

服务器I/O压力主要来源

  • 磁盘的I/O
  • 网络的I/O:一切皆是文件,本质是对socket文件的读写
网络I/O

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

结构图

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

软件是无法控制硬件的,需要经过内核程序的同意才可以调用硬件

过程:

当一个数据进入进入到内核空间,内核空间把请求转给用户程序,经过程序的分析数据需要的文件,再把所需文件数据通过内核,读取磁盘里的数据,再把数据缓存到内核上,经过程序包装成响应报文转给内核,通过内核的端口发给用户

网络I/O和磁盘I/O,每次I/O都要经由两个阶段:

第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长

第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短

I/O模型

同步/异步:

当程序进程做完数据准备之后,内核是否通知;如果通知为异步,不通知为同步

阻塞/非阻塞

当数据传输开始之后,要等待进程完成之前不能做其他事情;所以等待完成再进行下一个为阻塞,不等待而去做其他事,当通知再回来,为非阻塞

网络I/O模型

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

1、阻塞型 I/O模型------同步阻塞模式

当数据进入之后,该进程全程始终处于等待状态,然后当处理数据完成通知之后,才继续进行下一步

2、非阻塞型I/O模型------同步非阻塞模式

用户线程发起IO请求后,用户不会等待完数据处理完成,但是会频繁的一直检测数据是否准备好了没有,当检测到数据准备好了,会等待数据的拷贝,等待响应报文传回用户,所以是同步的非阻塞模式

3、信号驱动式 I/O模型------异步阻塞模式

信号驱动I/O,进程在当前发起请求进入之后不会等待,用户主程序可以继续执行,让内核在数据就绪时,发送信号通知进程,内核会为该进程产生一个信号回调函数,用户主程序等待数据从内核空间拷贝到用户空间,发响应报文数据回来。

优点:当数据还没准备好的时候可以进行其他数据处理,当处理数据完成信号发来是,再返回该进程,降低系统开销

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

4、多路复用I/O型------异步非阻塞模式

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

的IO,即复用同一个线程

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

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

5、信号驱动式I/O模型-----同步非阻塞模式

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

五种IO对比

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

I/O的具体实现方式

I/O常见实现

Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统

版本上面的实现方式不尽相同,主要有以下实现方式:

1、select:进行列表模式,最大并发限制1024

2、poll:非限制的列表模式

3、epoll:非限制的信号表模式,当数据处理准备好之后会亮灯发出信号,然后需要哪个数据,会直接进行数据封包发响应报文给用户,最好的模式

***Apcach与Nginx对比,为啥Nginx性能好?

因为Apcach是同步阻塞和异步阻塞的模式,处理数据的时候要进行等待数据处理完成,相对来说较为稳定,但是所用时间和会较长,无法高性能的并行处理数据;Nginx会有一个IO复用池,发给内核,让内核一个个进行数据处理,无需等待数据处理拷贝完成,就可以进行其他进程请求处理,当数据处理完后,回来调取数据进行封包,发响应报文,可以更快更高效的处理数据,所以Nginx会高性能

Nginx架构

1.Nginx功能介绍
  • 静态的web资源服务器html,图片,js,css,txt等静态资源
  • http/https协议的反向代理
  • 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
  • tcp/udp协议的请求转发(反向代理)
  • imap4/pop3协议的反向代理
2.基础特性

模块化设计,较好的扩展性

高可靠性

支持热部署:不停机更新配置文件,升级版本,更换日志文件

低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存

3.Nginx进程结构

Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组成

安装Nginx1.24

basic 复制代码
[root@Nginx ~]# wget https://nginx.org/en/download.html
[root@Nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y #安装依赖环境
[root@Nginx nginx-1.24.0]# useradd -s /sbin/nologin -M nginx


[root@webServer ~]# cd /mnt
[root@webServer mnt]# ls
hgfs  nginx-1.24.0.tar.gz
[root@webServer mnt]# tar zxf nginx-1.24.0.tar.gz 
[root@webServer mnt]# cd nginx-1.24.0/

#编译版本
[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@Nginx nginx-1.24.0]# make && make install

命令解释:

命令 说明
--user=nginx 指定nginx运行用户
--group=nginx 指定nginx运行组
--with-http_ssl_module 支持https://
--with-http_v2_module 支持http版本2
--with-http_realip_module 支持ip透传
--with-http_stub_status_module 支持状态页面
--with-http_gzip_static_module 支持压缩
--with-pcre 支持正则
--with-stream 支持tcp反向代理
--with-stream_ssl_module 支持tcp的ssl加密
--with-stream_realip_module 支持tcp的透传ip
nginx完成安装以后,有四个主要的目录

conf html logs sbin

bash 复制代码
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf 	html 	logs 	sbin

conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他
的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params
两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀
去掉即可。

html:目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web
文件是默认的错误页面提示页面。

logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比
如/var/logs/nginx里面。

sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。

新老版本平滑升级

  • 将旧Nginx二进制文件换成新Nginx程序文件(注意先备份)
  • 向master进程发送USR2信号
  • master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin
  • master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进程的PID存放至新生成的pid文件nginx.pid
  • 向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止
  • 向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件
  • 当升级有问题,可以回滚∶向老master发送HUP,向新master发送QUIT

运行配置:

bash 复制代码
[root@Nginx nginx]# tar zxf nginx-1.26.1.tar.gz
[root@webServer ~]# cd /mnt/nginx-1.26.1/

#查看两个版本
[root@webServer nginx-1.26.1]# ll objs/nginx /usr/local/nginx/sbin/nginx 
-rwxr-xr-x 1 root root 5746880 Jul 23 21:43 objs/nginx
-rwxr-xr-x 1 root root 5671480 Jul 23 15:54 /usr/local/nginx/sbin/nginx

#备份旧版本的Nginx的命令
[root@webServer nginx-1.26.1]# cd /usr/local/nginx/sbin/
[root@webServer sbin]# cp nginx nginx.24

#把新版本的nginx命令复制过去
[root@webServer sbin]# \cp -f /mnt/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/

#自检软件
[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]#  nginx
[root@webServer sbin]# ps aux | grep nginx
root      140408  0.0  0.1   9876  2052 ?        Ss   11:00   0:00 nginx: master process nginx
nginx     140409  0.0  0.2  14208  4996 ?        S    11:00   0:00 nginx: worker process
root      140618  0.0  0.1 221664  2304 pts/0    S+   11:00   0:00 grep --color=auto nginx

[root@webServer sbin]# kill -USR2 140408 			#nginx worker ID

#USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的
nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进
程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理

[root@webServer sbin]# ps aux | grep nginx
root      140408  0.0  0.1   9876  2564 ?        Ss   11:00   0:00 nginx: master process nginx
nginx     140409  0.0  0.2  14208  4996 ?        S    11:00   0:00 nginx: worker process
root      146551  0.0  0.3   9876  6528 ?        S    11:02   0:00 nginx: master process nginx
nginx     146552  0.0  0.2  14208  5124 ?        S    11:02   0:00 nginx: worker process
root      147924  0.0  0.1 221664  2304 pts/0    S+   11:02   0:00 grep --color=auto nginx

[root@webServer sbin]# kill -WINCH 140408

[root@webServer sbin]# curl  -I localhost
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Thu, 24 Jul 2025 03:09:04 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 23 Jul 2025 07:54:57 GMT
Connection: keep-alive
ETag: "68809551-267"
Accept-Ranges: bytes

#结束老版本的进程
[root@webServer sbin]# kill -9 140408
[root@webServer sbin]# ps aux | grep nginx
root      146551  0.0  0.3   9876  6528 ?        S    11:02   0:00 nginx: master process nginx
nginx     146552  0.0  0.2  14208  5252 ?        S    11:02   0:00 nginx: worker process
root      175555  0.0  0.1 221664  2304 pts/0    S+   11:12   0:00 grep --color=auto nginx

新版本回滚旧版本

basic 复制代码
[root@webServer sbin]# cp nginx nginx.26
[root@webServer sbin]# ls
nginx  nginx.24  nginx.26
[root@webServer sbin]# mv nginx.24 nginx
mv: overwrite 'nginx'? yes
[root@webServer sbin]# kill -USR2 146551


[root@webServer sbin]# ps aux | grep nginx
root      146551  0.0  0.3   9876  6656 ?        S    11:02   0:00 nginx: master process nginx
nginx     183291  0.0  0.2  14224  5112 ?        S    11:14   0:00 nginx: worker process
root      186305  0.0  0.3   9872  6528 ?        S    11:15   0:00 nginx: master process nginx
nginx     186306  0.0  0.2  14204  5124 ?        S    11:15   0:00 nginx: worker process
root      186664  0.0  0.1 221664  2304 pts/0    S+   11:16   0:00 grep --color=auto nginx

#回收新的版本
[root@webServer sbin]# kill -WINCH 146551
[root@webServer sbin]# ps aux | grep nginx
root      146551  0.0  0.3   9876  6656 ?        S    11:02   0:00 nginx: master process nginx
root      186305  0.0  0.3   9872  6528 ?        S    11:15   0:00 nginx: master process nginx
nginx     186306  0.0  0.2  14204  5252 ?        S    11:15   0:00 nginx: worker process
root      196363  0.0  0.1 221664  2304 pts/0    S+   11:19   0:00 grep --color=auto nginx

#检查回滚回旧版本
[root@webServer sbin]# curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Thu, 24 Jul 2025 03:19:20 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 23 Jul 2025 07:54:57 GMT
Connection: keep-alive
ETag: "68809551-267"
Accept-Ranges: bytes

#杀死新版本
[root@webServer sbin]# kill -9 146551

[root@webServer sbin]# ps aux | grep nginx
root      186305  0.0  0.3   9872  6528 ?        S    11:15   0:00 nginx: master process nginx
nginx     186306  0.0  0.2  14204  5252 ?        S    11:15   0:00 nginx: worker process
root      197230  0.0  0.1 221664  2304 pts/0    S+   11:19   0:00 grep --color=auto nginx

配置Nginx的启动文件

注意:配置文件检查

root@Nginx \~\]# nginx -s reload

basic 复制代码
#配置文件
[root@webServer ~]# vim /lib/systemd/system/nginx.service

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

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

[Install]
WantedBy=multi-user.target

[root@Nginx ~]# wget https://nginx.org/download/nginx-1.24.0.tar.gz			#建议在Windows主机下载后,上传
[root@Nginx ~]# vim /root/nginx-1.24.0/auto/cc/gcc 							#关闭debug功能,减小内存占用
...内容省略...
# debug
# CFLAGS="$CFLAGS -g'
...内容省略...

[root@Nginx ~]# systemctl daemon-reload
[root@Nginx ~]# systemctl start nginx

#设置开机自启动
[root@webServer ~]# systemctl enable --now nginx.service

二、***Nginx的核心配置详解

1.全局配置

配置说明:

复制代码
user nginx nginx; 						#启动Nginx工作进程的用户和组
worker_processes [number | auto]; 		#启动Nginx工作进程的数量,一般设为和CPU核心数相同

#当前为4核CPU
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
#将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进
程独占以一核心CPU,但是可以保证此进程不运行在其他核心上,这就极大减少了nginx的工作进程在不同的
cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务
器的性能。

实现nginx的高并发配置

basic 复制代码
[root@Nginx ~]# ulimit -n 102400
#修改配置
[root@Nginx ~]# vim /etc/security/limits.conf
[root@Nginx ~]# vim /apps/nginx/conf/nginx.conf
[root@Nginx ~]# systemctl restart nginx


测试结果

bash 复制代码
[root@webServer logs]# ab -n100000 -c5000 http://192.168.147.20/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 192.168.147.20 (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:        nginx/1.20.1
Server Hostname:        192.168.147.20
Server Port:            80

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

Concurrency Level:      5000
Time taken for tests:   9.314 seconds
Complete requests:      100000
Failed requests:        112846
   (Connect: 0, Receive: 0, Length: 56704, Exceptions: 56142)
Total transferred:      11052216 bytes
HTML transferred:       921018 bytes
Requests per second:    10736.55 [#/sec] (mean)
Time per request:       465.699 [ms] (mean)
Time per request:       0.093 [ms] (mean, across all concurrent requests)
Transfer rate:          1158.82 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  216  30.7    211     334
Processing:    42  238  49.5    215     418
Waiting:        0   88  99.8      0     315
Total:        262  454  57.8    445     655

Percentage of the requests served within a certain time (ms)
  50%    445
  66%    474
  75%    497
  80%    514
  90%    538
  95%    549
  98%    567
  99%    588
 100%    655 (longest request)

Nginx核心配置示例

基于不同的IP、不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块

ngx_http_core_module实现。

新建一个PC web站点
bash 复制代码
#定义子配置文件路径
[root@Nginx ~]# mkdir /usr/local/nginx/conf.d/
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
http {
	...省略...
	#gzip	on;
	server {
		listen		80;
		server_name localhost;
		#charset koi8-r;

        #access_log  logs/host.access.log  main;
...省略....
}
include "/usr/local/nginx/conf.d/*.conf";			#在配置文件的最后面添加此行
													#注意不要放在最前面,会导致前面的命令无法生效

#创建虚拟主机网站配置
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	listen	80;							#网站发布的端口
	server_name www.zym.org;			#访问域名需要与主机名相同
	root 	/web/html;						#默认发布目录
	index	index.html						#默认发布的页面文件
}

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

#查看域名与主机名是否相同,如不相同需要更改
[root@Nginx ~]# cat /etc/hosts
[root@Nginx ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.147.22  webServer.zym.org       www.zym.org


[root@Nginx ~]# nginx -s reload
#访问测试
[root@node100 ~]# curl www.zym.org #注意在访问主机中设解析
webserver
root与alias

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

root示例:

basic 复制代码
server {
	listen 80;
	server_name www.zym.org;
	location / {
		root /web/html;
	}
	location /dirtest { 								#必须建立/mnt/dirtest才能访问
		root /mnt;
	}
}

[root@Nginx ~]# mkdir /mnt/dirtest/
[root@Nginx ~]# echo dirtest page > /mnt/dirtest/index.html
[root@Nginx ~]# nginx -s reload

#重启Nginx并访问测试
[root@node100 ~]# curl www.zym.org/dirtest/
dirtest page

2.alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于location上下文,此指令使用较少

alias示例:

basic 复制代码
server {
	listen 80;
	server_name www.zym.org;

	location / {
		root /web/html;
	}
	location /dirtest {
		root /mnt;
	}
	location /alias { 			#注意about后不要加/	
								#使用alias的时候uri后面如果加了斜杠,则下面的路径配置必须加斜杠,否则403
			alias /mnt/dirtest; #当访问alias的时候,会显示alias定义的/mnt/dirtest
里面的内容
	}
}


#重启Nginx并访问测试
[root@node100 ~]# curl www.zym.org/alias/
dirtest page

注意

location中使用root指令和alias指令的意义不同

bash 复制代码
root 	#给定的路径对应于location中的/uri左侧的/

alias	#给定的路径对应于location中的/uri的完整路径
location的详细使用

在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;

ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,

而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最

高的一个uri

uri是用户请求的字符串,即域名后面的web文件路径

然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理

此请求。

basic 复制代码
#语法规则:
location [ = | ~ | ~* | ^~ ] uri { ... }

= 			#用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求

^~ 			#用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头
			#对uri的最左边部分做匹配检查,不区分字符大小写

~ 			#用于标准uri前,表示包含正则表达式,并且区分大小写

~* 			#用于标准uri前,表示包含正则表达式,并且不区分大写

不带符号	  #匹配起始于此uri的所有的uri

\ 			 #用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号


#匹配优先级从高到低:
=, ^~, ~/~*, 不带符号
匹配案例
一、精确匹配

访问nginx 服务器的/logo.jpg的时候要显示指定html文件的内容,精确匹配一般用于匹配组织的logo等相对固定的URL,匹配优先级最高

bash 复制代码
[root@Nginx ~]# mkdir /web/images -p
[root@Nginx ~]# ls /web/images
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	listen 80;
	server_name www.zym.org;
    
    location / {
		root /web/html;
	location = /logo.png {
		root /webdata/nginx/timinglee.org/lee/images;
		}
	}
}

#上传logo.jpg图片到/web/images
#访问测试:
[root@node100 ~]# curl http://www.zym.org/logo.png
二、区分大小写

"~ " -------实现区分大小写的模糊匹配

因为 ~ 区分大小写,当用户的请求被执行匹配时发现location中定义的是小写的png,本次访问的uri匹配失败,后续继续往下匹配其他的location,没有的话报错给客户端

bash 复制代码
server {
	listen 80;
	server_name www.zym.org;
	location / {
		root /web/html;
	}
	location ~ /logo.PNG {
		root /web/images;
	}
}

#重启Nginx
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# curl http://www.zym.org/logo.PNG		#访问失败,因为没有这个logo.PNG文件
三、不区分大小写

~* ------不区分大小写的模糊匹配

用来对用户请求的uri做模糊匹配,uri中无论都是大写、都是小写或者大小写混合,此模式也都会匹配,通常使用此模式匹配用户request中的静态资源并继续做下一步操作,此方式使用较多

Note

注意: 此方式中,对于Linux文件系统上的文件仍然是区分大小写的,如果磁盘文件不存在,仍会提示404

bash 复制代码
server {
	listen 80;
	server_name www.zym.org;
	location / {
		root /web/html;
		}
	location ~* /logo.png {
		root /web/images;
	}
}

#重启Nginx并访问测试
#http://www.zym.org/logo.png
四、URI开始
bash 复制代码
[root@Nginx ~]# mkdir /web/images/images{1,2}
[root@Nginx ~]# echo image1 > /web/images/images1/index.html
[root@Nginx ~]# echo image1 > /web/images/images2/index.html

#vhosts.conf配置文件
server {
	listen 80;
	server_name lee.timinglee.org;
	location / {
		root /web/html;
	}
	location ^~ /images {
		root /web/images;
		index index.html;
	}
	location /images1 {
		root /web/images;
	}
}

#重启Nginx并访问测试,实现效果是访问/images1和/images2返回内容一样
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# curl 192.168.147.22/images1/
image1
[root@Nginx ~]# curl 192.168.147.22/images2/
image1

五、文件名后缀

bash 复制代码
[root@Nginx ~]# mkdir /web/images

#上传一个图片到/web/images文件夹里
server {
	listen 80;
	server_name www.zym.org;
	location / {
		root /web/html;
	}
	location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js|css)$ {
		root /web/images;
		index index.html;
	}
}

#重启Nginx并访问测试
192.168.147.22/logo.png
优先级匹配
bash 复制代码
server {
	listen 80;
	server_name www.zym.org;
	location / {
		root /web/html;
	}
	location ^~ /images {
		root /web/images;
		index index.html;
	}
	location /images1 {
		root /web/images;
	}
	location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$ {
		root /data/nginx/static3;
		index index.html;
	}
}

#匹配优先级:=, ^~, ~/~*,/
location优先级:(location =精准匹配) > (location ^~ 路径) > (location ~,~* 正则顺序) >
(location 完整路径) > (location 部分起始路径) > (/)
#进行访问
Nginx账户认证
  • 由 ngx_http_auth_basic_module 模块提供此功能
bash 复制代码
#-b 表示非交互建立用户认证
[root@webServer ~]# htpasswd -cmb /usr/local/nginx/conf/.htpasswd admin zym
Adding password for user admin
[root@webServer ~]# htpasswd -mb /usr/local/nginx/conf/.htpasswd zym zym
Adding password for user zym

[root@webServer ~]# cat /usr/local/nginx/conf/.htpasswd 
admin:$apr1$qNheWQVX$uyPZT6lFgOqMXGvG4TA62.
zym:$apr1$CNCaKaFU$Te8Sq041Mh40brEEFO8WZ.

[root@webServer ~]# mkdir /web/login
[root@webServer ~]# echo login > /web/login/index.html
[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf 
#
server  {
    listen      80;
    server_name webServer.zym.org;

    location /login {
    root        /web;
    index       index.html;
    auth_basic "login password";
    auth_basic_user_file "/usr/local/nginx/conf/.htpasswd";
    }
}
#


[root@webServer ~]# nginx -s reload
[root@webServer ~]# systemctl restart nginx.service 
#进行用户测试
[root@webServer ~]# curl webServer.zym.org/login/ -u zym:zym
login
[root@webServer ~]# curl webServer.zym.org/login/ -u admin:zym
login
自定义错误页面

自定义错误页,同时也可以用指定的响应状态码进行响应, 可用位置:http, server, location, if in,location

bash 复制代码
[root@webServer ~]# mkdir /web/errors -p
[root@webServer ~]# echo error page > /web/errors/40x.html

[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf
#
server  {
    listen      80;
    server_name webServer.zym.org;
    error_page 404 /40x.html;
     
    location = /40x.html {
        root /web/errors;

     }
}
#

#检查代码错误
[root@webServer ~]# nginx -s reload
[root@webServer ~]# systemctl restart nginx.service

#测试结果
[root@webServer ~]# curl webServer.zym.org/zym
error page
自定义错误日志
bash 复制代码
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

示例配置

bash 复制代码
#首先创建文件
[root@Nginx ~]# mkdir "/var/log/nginx" -p

[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	listen 80;
	server_name webServer.zym.org;
	error_page 404 /40x.html;
	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;
	
	location = /40x.html {
		root /web/errors;
	}
}
#重启nginx并访问不存在的页面进行测试并验证是在指定目录生成新的日志文件
检测文件是否存在

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

语法格式:

bash 复制代码
Syntax: try_files file ... uri;
try_files file ... =code;
Default: ---
Context: server, location

如果不存在页面, 就转到default.html页面

bash 复制代码
[root@Nginx ~]# echo "index.html is not exist" >  /web/error/default.html

[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	
	listen 80;
	server_name webServer.zym.org;
	root /web/html;
	error_page 404 /40x.html;
	access_log /var/log/nginx/access.log;	#检查是否创建/var/log/nginx这个目录
	error_log /var/log/nginx/error.log;
	try_files $uri $uri.html $uri/index.html /error/default.html;
	
	location = /40x.html {
		root /web/errors;
	}
}
长连接配置
basic 复制代码
keepalive_timeout timeout [header_timeout]; #设定保持连接超时时长,0表示禁止长连接,默认为65s
											#通常配置在http字段作为站点全局配置
keepalive_requests 数字;				#在一次长连接上所允许请求的资源的最大数量
									#默认为100次,建议适当调大,比如:500

示例配置

  • 测试超时时,只需要一次测试过程完成后等待即可

  • 也可以测试限定次数 需要完成指定次数测试过程会自动断开

    #需配置主配置文件
    [root@webServer ~]# vim /usr/local/nginx/conf/nginx.conf
    #安装测试软件
    [root@webServer ~]# dnf install telnet -y
    [root@webServer ~]# telnet webServer.zym.org 80 #测试的地址要与访问的地址相同
    Trying 192.168.147.22...
    Connected to webServer.zym.org.
    Escape character is '^]'.
    GET / HTTP/1.1 #输入动作
    Host: webServer.zym.org #访问的host
    #按两次回车

    HTTP/1.1 200 OK
    Server: nginx/1.26.1
    Date: Sat, 26 Jul 2025 04:16:48 GMT
    Content-Type: text/html
    Content-Length: 11
    Last-Modified: Sat, 26 Jul 2025 03:51:15 GMT
    Connection: keep-alive
    ETag: "688450b3-b"
    Accept-Ranges: bytes

测试结果:

作为下载服务器配置
  • ngx_http_autoindex_module 模块处理以斜杠字符 "/" 结尾的请求,并生成目录列表,可以做为下载服务配置使用

    autoindex on | off; #自动文件索引功能,默为off
    autoindex_exact_size on | off; #计算文件确切大小(单位bytes),off 显示大概大小(单位K、
    M),默认on

    autoindex_localtime on | off ; #显示本机时间而非GMT(格林威治)时间,默认off
    autoindex_format html | xml | json | jsonp; #显示索引的页面文件风格,默认html

    limit_rate rate; #限制响应客户端传输速率(除GET和HEAD以外的所有方法),单位
    B/s,bytes/second #默认值0,表示无限制,此指令由
    ngx_http_core_module提供
    set $limit_rate 4k; #也可以通变量限速,单位B/s,同时设置,此项优级高.

实现服务器作为下载站点

bash 复制代码
[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf 
#
server  {
    listen      80;
    server_name webServer.zym.org;
    error_page 404 /40x.html;
    root /web/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 /errors/default.html;

    location = /40x.html {
        root /web/errors;

    }

    location /download {
        autoindex on;						#自动索引功能
        autoindex_exact_size on;			#计算文件确切大小(单位bytes),此为默认值,off只显示
大概大小(单位kb、mb、gb)
        autoindex_localtime on;				#on表示显示本机时间而非GMT(格林威治)时间,默为为off显
示GMT时间
		#set $limit_rate 1024k;					#限速,默认不限速
    }
}
#
[root@webServer ~]# nginx -s reload

限速设置

limit_rate 1024k------最大速度

下载测试

basic 复制代码
#实验素材建立
[root@webServer ~]# mkdir /web/download
[root@webServer ~]# dd if=/dev/zero of=/web/download/zym bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 1.87091 s, 280 MB/s

三、Nginx高级配置

1、Nginx状态页

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

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

bash 复制代码
server  {
    listen  80;
    server_name www.zym.org;
    error_page 404 /40x.html;
    root /web/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 /errors/default.html;

    location = /40x.html {
        root /web/errors;

    }

    location /status {
        stub_status;
    }
}

在Windows主机上,添加上www.zym.org的解析

文件位置:C:\Windows\System32\drivers\etc

192.168.147.22 www.zym.org

复制代码
    location = /40x.html {
        root /web/errors;
    
    }
    
    location /status {
        stub_status;
    }

}

2、Nginx压缩功能

bash 复制代码
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
		gzip on;
		gzip_comp_level 4;
		gzip_disable "MSIE [1-6]\.";
		gzip_min_length 4k;
		gzip_http_version 1.1;
		gzip_vary on;
		gzip_static on;
[root@Nginx ~]# nginx -s reload
[root@Nginx ~]# du -sh /usr/local/nginx/logs/access.log
9.9M /usr/local/nginx/logs/access.log
[root@Nginx ~]# cp /usr/local/nginx/logs/access.log /web/html/big.html
[root@Nginx ~]# echo xxx > /web/html/small.html

测试

bash 复制代码
[root@Nginx ~]# curl --head --compressed 192.168.147.22/small.html
Accept-Ranges: bytes		#小于4k,不进行压缩

[root@Nginx ~]# curl --head --compressed 192.168.147.22/big.html
Content-Encoding: gzip		#大于4k,以gzip方式进行压缩

3、Nginx变量使用

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

常用内置变量

basic 复制代码
$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的程序编译
basic 复制代码
cd /mnt
rm -fr nginx-1.26.1
tar zxf echo-nginx-module-0.63.tar.gz
[rootdwebservera ~]# cd nginx-1.26.1
[root@webServer nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with_http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/mnt/echo-nginx-module-0.63 && make && make install
#查看信息
[rootdwebservera ~]# nginx -V
basic 复制代码
[rootdwebservera ~]# vim /usr/local/nginx/conf.d/vhosts.conf

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

四、Nginx Rewrite相关功能

ngx_http_rewrite_module模块指令

1、if指令

用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:

复制代码
if (条件匹配) {
	action
}

匹配成功时,条件为ture;反之,条件指令为false

bash 复制代码
= 		#比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!= 		#比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~ 		#区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ 	#区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~* 	#不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* 	#不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f 	#判断请求的文件是否存在和是否不存在
-d 和 !-d 	#判断请求的目录是否存在和是否不存在
-x 和 !-x 	#判断文件是否可执行和是否不可执行
-e 和 !-e 	#判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)

#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false

配置文件

bash 复制代码
[rootdwebservera ~]# vim /usr/local/nginx/conf.d/vhosts.conf
#
location /test {
	index index.html;
	default_type text/html;
	if ( $scheme = http ){
		echo "if ---------> $scheme";
	}
	if ( $scheme = https ){
		echo "if ---------> $scheme";
	}
}
location /test2 {
	if ( !-e $request_filename ){
		echo "$request_filename is not exist";
		return 409;
	}
}

测试:

复制代码
[rootdwebservera ~]# curl www.zym.org/test/
if ---------> http
2、set指令
  • 指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key
  • 另外set定义格式为set $key value,value可以是text, variables和两者的组合
bash 复制代码
[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 /test3{
	set $name lee;
	echo $name;
	}
}
测试:
[root@client ~]# curl lee.timinglee.org/test3
lee
3、break指令
  • 用于中断当前相同作用域(location)中的其他Nginx配置
  • 与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
  • 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
  • Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用

注意:只是不执行 ngx_http_rewrite_module模块的指令,其它指令还会执行

bash 复制代码
[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 /break{
		default_type text/html;
		set $name lee;
		echo $name;
		break;
		set $port $server_port;
        echo $port;
	}
}

测试

basic 复制代码
[root@client ~]# curl lee.timinglee.org/break #当未添加break时
lee
80

[root@client ~]# curl lee.timinglee.org/break #添加break后
lee
4、return指令

return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置

格式:

bash 复制代码
return code; 			#返回给客户端指定的HTTP状态码
return code [text]; 	#返回给客户端的状态码及响应报文的实体内容
						#可以调用变量,其中text如果有空格,需要用单或双引号
return code URL; 		#返回给客户端的URL地址
basic 复制代码
server {
	listen 80;
	server_name lee.timinglee.org;
	root /webdata/nginx/timinglee.org/lee;
	location /return {
		default_type text/html;
		if ( !-e $request_filename){
			return 301 http://www.baidu.com;
			#return 666 "$request_filename is not exist";
		}
			echo "$request_filename is exist";
	}
}


#测试:
[root@client ~]# curl lee.timinglee.org/return
/webdata/nginx/timinglee.org/lee/return is exist
[root@client ~]# curl lee.timinglee.org/return1
/webdata/nginx/timinglee.org/lee/return1 is not exist

#测试return 301 http://www.baidu.com;
可在浏览器直接访问lee.timinglee.org/return1

rewrite指令

1、rewrite flag使用介绍

利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型

  • 跳转型指由客户端浏览器重新对新地址进行请求
  • 代理型是在WEB服务器内部实现跳转

rewrite的格式

bash 复制代码
Syntax: rewrite regex replacement [flag];
#通过正则表达式处理用户请求并返回替换后的数据包。

Default: -
Context: server, location, if
2、flag说明
指令 说明
redirect; 临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端 由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent; 重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端 由客户端重新发起请求,状态码:301
break; 重写完成后,停止对当前URL在当前location中后续的其它重写操作 而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用 适用于一个URL一次重写
last; 重写完成后,停止对当前URI在当前location中后续的其它重写操作 对新的URL启动新一轮重写检查,不建议在location中使用 适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
3、rewrite案例:域名永久与临时重定向
  • 域名的临时的调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳转,这种情况浏览器不会缓存跳转,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存

配置

basic 复制代码
location / {
	root /web/shtml/pc;
	index index.html;
	rewrite / http://www.zym.com permanent;
	#rewrite / http://www.zym.com redirect;
}

#重启Nginx并访问域名 http://www.timinglee.org 进行测试
永久重定向---301
  • 域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录可以缓存到客户端浏览器
  • 永久重定向会缓存DNS解析记录, 浏览器中有 from disk cache 信息,即使nginx服务器无法访问,浏览器也会利用缓存进行重定向
basic 复制代码
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	listen 80;
	server_name www.zym.org;
	root /web;
	location / {
		#rewrite / http://www.zym.com redirect;
		rewrite / http://www.zym.com permanent;
	}
}

server {
	listen 80;
	server_name www.zym.com;
	root /web;
}
临时重定向---302
  • 域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器不会缓存当前域名的解析记录,而浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最大的本质区别。

即当nginx服务器无法访问时,浏览器不能利用缓存,而导致重定向失败

basic 复制代码
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;
}
4、rewrite案例: break与last区别

rewrite ... break 会终止当前 location 内的后续 rewrite 处理

rewrite ... last标记会让请求重新进入路由匹配 (相当于新请求),若 /test1 有独立 location(如你配置的 location /test1),会直接匹配到 /test1逻辑,而非继续执行当前 location 后续的rewrite

bash 复制代码
[root@webServer ~]# mkdir /web/html/{test1,test2,break,last}

#编写内容
[root@webServer ~]# echo test1 > /web/html/test1/index.html
[root@webServer ~]# echo test2 > /web/html/test2/index.html
[root@webServer ~]# echo break > /web/html/break/index.html
[root@webServer ~]# echo last > /web/html/last/index.html

#配置vhosts.conf文件
[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf
#
server  {
    listen 80;
    server_name www.zym.org;
    root /web/html;
    index index.html;

    location = /break {
        root /web/html;
        rewrite ^/break/(.*) /test1/$1 break;
        rewrite ^/test1/(.*) /test2/$1;

    }
#`rewrite ... break` 会终止当前 `location` 内的后续 rewrite 处理
    
    location /last {
        root /web/html;
        rewrite ^/last/(.*) /test1/$1 last;
        rewrite ^/test1/(.*) /test2/$1;
    }
#`rewrite ... last`标记会让请求**重新进入路由匹配**(相当于新请求),若` /test1` 有独立 `location`(如你配置的 `location /test1`),会直接匹配到 `/test1`逻辑,而非继续执行当前 `location `后续的`rewrite`

    location  /test1 {
        default_type text/html;
        return 666 "new test1";
    }
    location /test2 {
        root /web/html;
        }
}
#

[root@webServer ~]# curl  -L www.zym.org/last/index.html
new test1
[root@webServer ~]# curl  -L www.zym.org/break/index.html
test1

Nginx防盗链

​ 防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链

referer就是之前的那个网站域名,正常的referer信息有以下几种:

bash 复制代码
none:				#请求报文首部没有referer首部,
					#比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked:			#请求报文有referer首部,但无有效值,比如为空。
server_names:		#referer首部中包含本主机名及即nginx 监听的server_name。

arbitrary_string: 	#自定义指定字符串,但可使用*作通配符。
					#示例:*.zym.org或者www.zym.*

regular expression:	#被指定的正则表达式模式匹配到的字符串,要使用~开头
					#例如:~.*\.zym\.com
1、实现盗链

在一个web 站点盗链另一个站点的资源信息,比如:图片、视频等

bash 复制代码
#新建一个主机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"
2、实现防盗链
  • 基于访问安全考虑,nginx支持通过ngx_http_referer_module模块,检查访问请求的referer信息是否有效
bash 复制代码
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
	listen 80;
	server_name www.timinglee.org;
	root /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反向代理


  • Nginx的反向代理:做访问的限制

  • Nginx的正向代理:做访问的代理

5.1 实现http反向代理

5.1.1 实战案例:指定location实现反向代理

指定的location

复制代码
server  {
    listen 80;
    server_name www.zym.org;

    location / {
        proxy_pass http://192.168.147.20;
    }
    location ~ /static/ {
        proxy_pass http://192.168.147.10:80;
    }
}

后端web服务器必须要有相对于的访问URL

basic 复制代码
[root@RS1 ~]# systemctl start httpd
[root@RS1 ~]# mkdir /var/www/html/static
[root@RS1 ~]# echo static 192.168.147.10 > /var/www/html/static/index.html
[root@RS2 ~]# echo 192.168.147.20 > /var/www/html/index.html

访问测试


5.1.2 反向代理示例:缓存功能

准备缓存配置

basic 复制代码
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
@@@@内容省略@@@@
#配置在nginx.conf http配置段

#gzip  on;
     proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2
     keys_zone=proxycache:20m

[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf
	server  {
    listen 80;
    server_name www.zym.org;

    location ~ /static/ {
        proxy_pass http://192.168.147.10:80;
        proxy_cache proxycache;
        proxy_cache_key $request_uri;
        proxy_cache_valid 200 302 301 10m;
        proxy_cache_valid any 1m;
    }
}

#/data/nginx/proxycache/ 目录会自动生成
#/usr/local/nginx/proxy_cache 会自动生成

[root@webServer ~]# ll /usr/local/nginx/proxy_cache -d
drwx------ 2 nginx root 6 Jul 27 16:02 /usr/local/nginx/proxy_cache

[root@webServer ~]# tree  /usr/local/nginx/proxy_cache
/usr/local/nginx/proxy_cache

0 directories, 0 files

访问并验证缓存文件

basic 复制代码
[root@webServer ~]# ab -n1000 -c100 http://www.zym.org/static/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 www.zym.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.1
Server Hostname:        www.zym.org
Server Port:            80

Document Path:          /static/index.html
Document Length:        22 bytes

Concurrency Level:      100
Time taken for tests:   0.070 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      273000 bytes
HTML transferred:       22000 bytes
Requests per second:    14210.00 [#/sec] (mean)
Time per request:       7.037 [ms] (mean)
Time per request:       0.070 [ms] (mean, across all concurrent requests)
Transfer rate:          3788.41 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3   0.5      3       4
Processing:     1    3   0.8      3       6
Waiting:        0    2   0.9      2       5
Total:          3    6   0.7      6       9

Percentage of the requests served within a certain time (ms)
  50%      6
  66%      7
  75%      7
  80%      7
  90%      7
  95%      7
  98%      8
  99%      8
 100%      9 (longest request)

缓存目录结构及文件大小

5.1.3 http反向代理负载均衡
  • 在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能
反向代理示例---后端多台web服务器
  1. 部署后端Apache服务器
basic 复制代码
[root@apache20 ~]# yum install httpd -y
[root@apache20 ~]# echo "web1 172.25.254.20" > /var/www/html/index.html
[root@apache20 ~]# systemctl enable --now httpd
[root@apache30 ~]# yum install httpd -y
[root@apache30 ~]# echo "web2 172.25.254.30" >> /var/www/html/index.html
[root@apache30 ~]# systemctl enable --now httpd


#访问测试
[root@centos8 ~]# curl http://172.25.254.20
web1 172.25.254.20
[root@centos8 ~]# curl http://172.25.254.30
web2 172.25.254.30
  1. 配置nginx反向代理
basic 复制代码
[root@centos8 ~]# cat /apps/nginx/conf/conf.d/pc.conf
upstream webserver {
	#ip_hash;
	#hash $request_uri consistent;
	#hash $cookie_lee
	#least_conn;
	server 172.25.254.20:8080 weight=1 fail_timeout=15s max_fails=3;
	server 172.25.254.30:80 weight=1 fail_timeout=15s max_fails=3;
	server 172.25.254.10:80 backup;
}
server {
	listen 80;
	server_name www.timinglee.org;
location ~ / {
	proxy_pass http://webserver;
	}
}
#重启Nginx 并访问测试
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.20 web
[Administrator.DESKTOP-P19CNDN] ➤ curl www.timinglee.org
172.25.254.30 web
#关闭172.25.254.20和172.25.254.30,测试nginx backup服务器可用性:
[Administrator.DESKTOP-P19CNDN] ➤ while true;do curl
http://www.timinglee.org;sleep 1;done

5.2 实现FastCGI

5.2.1 FastCGI实战案例 : Nginx与php-fpm在同一服务器

安装PHP

basic 复制代码
#解决php依赖
[root@Nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel

安装该依赖oniguruma-devel,需要自行下载该RPM包进行安装

basic 复制代码
[root@webServer beifen]# sudo dnf install /beifen/oniguruma-6.9.6-1.el9.6.x86_64.rpm -y
[root@webServer beifen]# sudo dnf install /beifen/oniguruma-devel-6.9.6-1.el9.6.x86_64.rpm -y

源码编译php

bash 复制代码
[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]# make && make install

PHP配置优化

basic 复制代码
[root@webServer php-8.3.9]# cd /usr/local/php/etc/
[root@webServer etc]# cp php-fpm.conf.default php-fpm.conf
[root@webServer etc]# vim php-fpm.conf
#去掉该注释
pid = run/php-fpm.pid 			#指定pid文件存放位置

[root@webServer etc]# cd php-fpm.d/
[root@webServer php-fpm.d]# cp www.conf.default www.conf
[root@webServer ~]# vim /usr/local/php/etc/php-fpm.d/www.conf
listen = 192.168.147.22:9000
  1. 生成配置文件
basic 复制代码
[root@webServer php-fpm.d]# cd /mnt/php-8.3.9/
[root@webServer php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini

[root@webServer php-8.3.9]# 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 #修改时区
  1. 生成启动文件
basic 复制代码
[root@webServer ~]# cd /mnt/php-8.3.9/
[root@webServer php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/php-fpm.service
[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 			#注释该内容 

#刷新注释文件
[root@webServer var]# systemctl daemon-reload 
[root@webServer var]# systemctl start php-fpm
[root@webServer var]# netstat -antlupe | grep php

Nginx配置转发

basic 复制代码
[root@webServer ~]# vim /usr/local/nginx/conf.d/vhosts.conf

server  {
    listen 80;
    server_name www.zym.org;
    root /data/php;
    location ~ \.php$ {
        fastcgi_pass 192.168.147.22:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
        include fastcgi.conf;
    }
}

在浏览器进行访问测试

添加php环境变量

basic 复制代码
[root@webServer memcache-8.2]# vim ~/.bash_profile 

# .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:/usr/local/php/sbin
5.2.2 php的动态扩展模块(php的缓存模块)

过程说明:

安装memcache模块

memcache-8.2.tgz需自行网站下载

basic 复制代码
[root@webServer ~]# cd /mnt/
[root@webServer mnt]# tar zxf memcache-8.2.tgz 
[root@webServer mnt]# cd memcache-8.2/
[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
[root@webServer memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
memcache.so  opcache.so

复制测试文件到nginx发布目录中

basic 复制代码
[root@webServer 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

复制测试文件

bash 复制代码
[root@Nginx memcache-8.2]# cp example.php memcache.php /data/php/

[root@Nginx ~]# vim /data/php/memcache.php
define('ADMIN_USERNAME','zym'); // Admin Username
define('ADMIN_PASSWORD','zym'); // 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模块

bash 复制代码
[root@webServer memcache-8.2]# vim /usr/local/php/etc/php.ini
974 ;extension=zip
975 extension=memcache
976 ;zend_extension=opcache

[root@webServer memcache-8.2]# systemctl reload php-fpm.service 
[root@webServer memcache-8.2]# php -m | grep mem
memcache

部署memcached

basic 复制代码
[root@webServer memcache-8.2]# yum install memcached -y

[root@webServer memcache-8.2]# systemctl enable --now memcached.service

[root@webServer memcache-8.2]# netstat -antlupe | grep memcache
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      980        2140961    1390340/memcached   
tcp6       0      0 ::1:11211               :::*                    LISTEN      980        2140962    1390340/memcached 

[root@webServer memcache-8.2]# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"

测试

bash 复制代码
访问:http://www.zym.org/memcache.php		#查看命中效果

访问:http://www.zym.org/example.php

5.3 php高速缓存

部署方法

在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所以nginx需要重新编译

basic 复制代码
[root@Nginx ~]# rm -fr /apps/nginx/
[root@Nginx ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@Nginx ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@Nginx ~]# cd nginx-1.26.1/
[root@Nginx nginx-1.26.1]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --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
[root@Nginx nginx-1.26.1]# make && make install
[root@Nginx ~]# vim /apps/nginx/conf.d/php.conf
upstream memcache {
	server 127.0.0.1:11211;
	keepalive 512;
}
server {
	listen 80;
	server_name php.timinglee.org;
	root /data/php;
location /memc {
	internal;
	memc_connect_timeout 100ms;
	memc_send_timeout 100ms;
	memc_read_timeout 100ms;
	set $memc_key $query_string; #使用内置变量$query_string来作为key
	set $memc_exptime 300; #缓存失效时间300秒
	memc_pass memcache;
}
location ~ \.php$ {
	set $key $uri$args; 			#设定key的值
	srcache_fetch GET /memc $key; 	#检测mem中是否有要访问的php
	srcache_store PUT /memc $key; 	#缓存为加载的php数据
	fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
	include fastcgi.conf;
	}
}
[root@Nginx ~]# systemctl start nginx.servic

测试结果:

basic 复制代码
[root@apache20 ~]# ab -n500 -c10 http://php.timinglee.org/index.php
Concurrency Level: 10
Time taken for tests: 0.255 seconds
Complete requests: 500
Failed requests: 0

六、nginx二次开发版本

6.1 openresty

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关

  • 中国人章亦春把 LuaJIT VM 嵌入到 Nginx 中,实现了 OpenResty 这个高性能服务端解决方案
  • OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将Nginx有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
  • OpenResty 由于有功能强大且方便的的API,可扩展性更强,如果需要实现定制功能,OpenResty是个不错的选择

官网: http://openresty.org/cn/

6.2 编译安装 openresty

basic 复制代码
[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

另外版本

basic 复制代码
[root@Nginx ~]#dnf -y install gcc pcre-devel openssl-devel perl	# 安装依赖
[root@Nginx ~]#useradd -r -s /sbin/nologin nginx	# 创建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=/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@Nginx openresty-1.17.8.2]#gmake && gmake install	# 编译安装
[root@Nginx openresty-1.17.8.2]#ln -s /apps/openresty/bin/* /usr/bin/		#创建链接 方便使用
[root@Nginx openresty-1.17.8.2]#openresty -v	# 查看openresty的版本
nginx version: openresty/1.17.8.2

[root@webServer openresty-1.17.8.2]# systemctl stop nginx.service
[root@Nginx openresty-1.17.8.2]# openresty 		# 启动openresty
[root@webServer openresty-1.17.8.2]# echo 172.25.254.55 from openresty > /usr/local/openresty/nginx/html/index.html
[root@webServer openresty-1.17.8.2]# curl 172.25.254.55

注意:

如果无法启动服务,提示

因为端口被占用,查看端口

bash 复制代码
[root@webServer openresty-1.17.8.2]# lsof -i :80
COMMAND       PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
openresty 1579484  root    6u  IPv4 2442325      0t0  TCP *:http (LISTEN)
openresty 1579485 nginx    6u  IPv4 2442325      0t0  TCP *:http (LISTEN)

#把占用端口删掉,重启服务
[root@webServer openresty-1.17.8.2]# kill -9 1579484 1579485
[root@webServer openresty-1.17.8.2]# openresty