目录
一、Web 服务基础介绍
1.1 Apache 经典的 Web 服务端
Apache起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发
目前经历了两大版本分别是1.X和2.X
其可以通过编译安装实现特定的功能
1.1.1 Apache prefork 模型
预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
每个子进程有一个独立的线程响应用户请求
相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.1.2 Apache worker 模型
一种多进程和多线程混合的模型
有一个控制进程,启动多个子进程
每个子进程里面包含固定的线程 使用线程程来处理请求
当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求
由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
1.1.3 Apache event模型
Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)
每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
1.2 Nginx 高性能的 Web 服务端
Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发工作最早从2002年开始,第一次公开发布时间是2004年10月4日,版本号是0.1.0
2019年3月11日F5 与 NGINX达成协议,F5 将收购 NGINX 的所有已发行股票,总价值约为 6.7 亿美元。 6.7亿美金约合44.97亿人民币,nginx核心模块代码长度198430(包括空格、注释),所以一行代码约为 2.2万人民币
官网地址 www.nginx.org
Nginx历经十几年的迭代更新(https://nginx.org/en/CHANGES), 目前功能已经非常完善且运行稳 定,另外Nginx的版本分为开发版、稳定版和过期版,nginx以功能丰富著称,它即可以作为http服务 器,也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求
支持FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以 上且开启stream模块)等功能,并且支持第三方的功能扩展。
天猫 淘宝 京东 小米 163 新浪等一线互联网公司都在用Nginx或者进行二次开发
基于Nginx的工作场景:
二、Nginx 架构和安装
2.1 Nginx 概述
2.1.1 Nginx 介绍
Nginx:engine X ,2002年开发,分为社区版和商业版(nginx plus )
Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器
解决C10K问题(10K Connections)
Nginx官网:http://nginx.org
nginx的其它的二次发行版:
- Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加 了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了 很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始, Tengine成为一个开源项目官网: http://tengine.taobao.org/
- OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发,官网:http://openresty.org/cn/
2.1.2 Nginx 功能介绍
静态的web资源服务器html,图片,js,css,txt等静态资源
http/https协议的反向代理
结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
tcp/udp协议的请求转发(反向代理)
imap4/pop3协议的反向代理
2.2 Nginx 架构和进程
2.2.1 Nginx 架构图
2.2.2 Nginx 进程结构
web请求处理机制
-
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直 到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务 器资源耗尽而无法提供请求
-
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客 户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器 对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可 以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作 了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组成。
2.3 Nginx 模块介绍
nginx 有多种模块
-
核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能
-
标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等
-
可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
-
邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
-
Stream服务模块: 实现反向代理功能,包括TCP协议代理
-
第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等
nginx高度模块化,但其模块早期不支持DSO机制;1.9.11 版本支持动态装载和卸载
模块分类:
核心模块:core module
标准模块:
HTTP 模块: ngx_http_*
HTTP Core modules #默认功能
HTTP Optional modules #需编译时指定
Mail 模块: ngx_mail_*
Stream 模块 ngx_stream_*
第三方模块
2.4 Nginx 安装
2.4.1 Nginx 版本和安装方式
Nginx版本
-
Mainline version 主要开发版本,一般为奇数版本号,比如1.19
-
Stable version 当前最新稳定版,一般为偶数版本,如:1.20
-
Legacy versions 旧的稳定版,一般为偶数版本,如:1.18
Nginx安装可以使用yum或源码安装,但是推荐使用源码编译安装
-
yum的版本比较旧
-
编译安装可以更方便自定义相关路径
-
使用源码编译可以自定义相关功能,更方便业务的上的使用
2.4.2.Nginx 编译安装
编译器介绍
源码安装需要提前准备标准的编译器,GCC的全称是(GNU Compiler collection),其有GNU开发,并以GPL即LGPL许可,是自由的类UNIX即苹果电脑Mac OS X操作系统的标准编译器,因为GCC原本只能处理C语言,所以原名为GNU C语言编译器,后来得到快速发展,可以处理C++,Fortran,pascal,objective C,java以及Ada等其他语言,此外还需要Automake工具,以完成自动创建Makefile的工作,Nginx的一些模块需要依赖第三方库,比如: pcre(支持rewrite),zlib(支持gzip模块)和openssl(支持ssl模块)等。
2.4.2.1 编译安装 Nginx 示例
官方源码包下载地址:
https://nginx.org/en/download.html
下载编译器已经其他依赖模块
[root@nginx-node1 ~]# dnf install -y gcc pcre-devel zlib-devel openssl-devel
创建nginx用户
[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
解压
[root@nginx-node1 ~]# tar zxf nginx-1.24.0.tar.gz
[root@nginx-node1 ~]# cd nginx-1.24.0/
[root@nginx-node1 nginx-1.24.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
检测,设置编译参数
[root@nginx-node1 nginx-1.24.0]# ./configure --help | less
[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
--user=nginx \ # 指定nginx运行用户
--group=nginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip
关闭debug功能
[root@nginx-node1 nginx-1.24.0]# vim auto/cc/gcc
....................
# debug
#CFLAGS="$CFLAGS -g"
....................
编译
[root@nginx-node1 nginx-1.24.0]# make && make install
配置本地环境变量
[root@nginx-node1 nginx-1.24.0]# vim ~/.bash_profile
....................
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx-node1 nginx-1.24.0]# source ~/.bash_profile
启动nginx
[root@nginx-node1 ~]# nginx
隐藏版本信息
[root@nginx-node1 objs]# vim /root/nginx-1.24.0/src/core/nginx.h
....................
#define NGINX_VERSION "1.0"
#define NGINX_VER "zty/" NGINX_VERSION
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二进制启动脚本,可以接受不同的参数以实现不同的功能。
2.4.2.2 验证版本及编译参数
[root@nginx-node1 ~]# nginx -V
nginx version: zty/1.0
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module
2.4.2.3 使用安装完成的二进制文件nginx
[root@nginx-node1 ~]# nginx -h
nginx version: zty/1.0
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
[-e filename] [-c filename] [-g directives]
Options:
-?,-h : this help
-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 #测试并打印
-q : suppress non-error messages during configuration testing #静默模式
-s signal : send signal to a master process: stop, quit, reopen, reload #发送信号号,reload信号 会生成新的worker,但master不会重新生成
-p prefix : set prefix path (default: /usr/local/nginx/) #指定Nginx 目录
-e filename : set error log file (default: logs/error.log)
-c filename : set configuration file (default: conf/nginx.conf) #配置文件路径
-g directives : set global directives out of configuration file #设置全局指令,注意和配置文件不要同时配置,否则冲突
2.4.2.4 Nginx 启动文件
[root@nginx-node1 ~]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
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-node1 ~]# systemctl daemon-reload
[root@nginx-node1 ~]# systemctl enable --now nginx.service
2.5 平滑升级和回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时 Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
2.5.1 平滑升级流程
-
将旧Nginx二进制文件换成新Nginx程序文件(注意先备份)
-
向master进程发送USR2信号
-
master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin
-
master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主 进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进 程的PID存放至新生成的pid文件nginx.pid
-
向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止
-
向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件
-
如果发现升级有问题,可以回滚∶向老master发送HUP,向新master发送QUIT
2.5.2 平滑升级和回滚案例
解压nginx新版本和模块
[root@nginx-node1 ~]# tar zxf echo-nginx-module-0.63.tar.gz
[root@nginx-node1 ~]# tar zxf nginx-1.26.1.tar.gz
[root@nginx-node1 ~]# cd nginx-1.26.1/
开始编译新版本
[root@nginx-node1 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_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx-node1 nginx-1.26.1]# make #只要make无需要make install
把之前的旧版的nginx命令备份
[root@nginx-node1 ~]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ll
总用量 1208
-rwxr-xr-x 1 root root 1235800 8月 15 11:16 nginx
[root@nginx-node1 sbin]# cp nginx nginx.old
把新版本的nginx命令复制过去
[root@nginx-node1 sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/nginx
检测一下有没有问题
[root@nginx-node1 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
USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的 nginx
此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
[root@nginx-node1 sbin]# ps aux | grep nginx
root 52114 0.0 0.0 9860 932 ? Ss 14:04 0:00 nginx: master process nginx
nginx 52115 0.0 0.2 13756 4724 ? S 14:04 0:00 nginx: worker process
root 52117 0.0 0.1 221680 2348 pts/0 S+ 14:04 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -USR2 52114
[root@nginx-node1 sbin]# ps aux | grep nginx
root 52114 0.0 0.1 9860 2572 ? Ss 14:04 0:00 nginx: master process nginx
nginx 52115 0.0 0.2 13756 4724 ? S 14:04 0:00 nginx: worker process
root 52122 0.0 0.3 9760 6100 ? S 14:05 0:00 nginx: master process nginx
nginx 52123 0.0 0.2 13788 4800 ? S 14:05 0:00 nginx: worker process
root 52125 0.0 0.1 221680 2364 pts/0 S+ 14:05 0:00 grep --color=auto nginx
检测版本信息 依旧是旧版本生生效
[root@nginx-node1 sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: zty/1.0
Date: Thu, 15 Aug 2024 06:06:14 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 06:03:42 GMT
Connection: keep-alive
ETag: "66bd9a3e-267"
Accept-Ranges: bytes
回收旧版本
[root@nginx-node1 sbin]# kill -WINCH 52114
[root@nginx-node1 sbin]# ps aux | grep nginx
root 52114 0.0 0.1 9860 2572 ? Ss 14:04 0:00 nginx: master process nginx
root 52122 0.0 0.3 9760 6100 ? S 14:05 0:00 nginx: master process nginx
nginx 52123 0.0 0.2 13788 4800 ? S 14:05 0:00 nginx: worker process
root 52128 0.0 0.1 221680 2352 pts/0 S+ 14:06 0:00 grep --color=auto nginx
检测版本信息 新版本生效
[root@nginx-node1 sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Thu, 15 Aug 2024 06:06:37 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 06:03:42 GMT
Connection: keep-alive
ETag: "66bd9a3e-267"
Accept-Ranges: bytes
回滚
如果升级的版本发现问题需要回滚,可以重新拉起旧版本的worker
[root@nginx-node1 sbin]# cp nginx nginx.new
[root@nginx-node1 sbin]# \cp -f /root/nginx-1.24.0/objs/nginx /usr/local/nginx/sbin/nginx
[root@nginx-node1 sbin]# kill -HUP 52114
[root@nginx-node1 sbin]# ps aux | grep nginx
root 52114 0.0 0.1 9860 2572 ? Ss 14:04 0:00 nginx: master process nginx
root 52122 0.0 0.3 9760 6100 ? S 14:05 0:00 nginx: master process nginx
nginx 52123 0.0 0.2 13788 4800 ? S 14:05 0:00 nginx: worker process
nginx 52153 0.0 0.2 13756 4724 ? S 14:10 0:00 nginx: worker process
root 52155 0.0 0.1 221680 2360 pts/0 S+ 14:11 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -WINCH 52122
[root@nginx-node1 sbin]# ps aux | grep nginx
root 52114 0.0 0.1 9860 2572 ? Ss 14:04 0:00 nginx: master process nginx
root 52122 0.0 0.3 9760 6100 ? S 14:05 0:00 nginx: master process nginx
nginx 52153 0.0 0.2 13756 4724 ? S 14:10 0:00 nginx: worker process
root 52158 0.0 0.1 221680 2340 pts/0 S+ 14:12 0:00 grep --color=auto nginx
版本回滚完成
[root@nginx-node1 sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: zty/1.0
Date: Thu, 15 Aug 2024 06:12:31 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 06:03:42 GMT
Connection: keep-alive
ETag: "66bd9a3e-267"
Accept-Ranges: bytes
三、Nginx 核心配置详解
3.1 配置文件说明
nginx 官方帮助文档:http://nginx.org/en/docs/
Nginx的配置文件的组成部分:
-
主配置文件:nginx.conf
-
子配置文件: include conf.d/*.conf
-
fastcgi, uwsgi,cgi 等协议相关的配置文件
-
mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮
-
件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动
-
使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式
nginx 配置文件格式说明
配置文件由指令与指令块构成
每条指令以;分号结尾,指令与值之间以空格符号分隔
可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐
指令块以{ }大括号将多条指令组织在一起,且可以嵌套指令块
include语句允许组合多个配置文件以提升可维护性
使用#符号添加注释,提高可读性
使用$符号使用变量
部分指令的参数支持正则表达式
Nginx 主配置文件的配置指令方式:
directive value [value2 ...];
注意
(1) 指令必须以分号结尾
(2) 支持使用配置变量
内建变量:由Nginx模块引入,可直接引用
自定义变量:由用户使用set命令定义,格式: set variable_name value;
引用变量:$variable_name
主配置文件结构:四部分
main block:主配置段,即全局配置段,对http,mail都有效
#事件驱动相关的配置
event {
...
}
#http/https 协议相关配置段
http {
...
}
#默认配置文件不包括下面两个块
#mail 协议相关配置段
mail {
...
}
#stream 服务器相关配置段
stream {
...
}
默认的nginx.conf 配置文件格式说明
#全局配置端,对全局生效,主要设置nginx的启动用户/组,启动的工作进程数量,工作模式,Nginx的PID路径,日志路径等。
user nginx nginx;
worker_processes 1; #启动工作进程数数量
events { #events #设置快,主要影响nginx服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型
#处理请求,每个工作进程可以同时支持的最大连接数,是否开启对多工作进程下的网络连接进行序列化等。
worker_connections 1024; #设置单个nginx工作进程可以接受的最大并发,作为web服务器的时候最大并发数为 #worker_connections * worker_processes,作为反向代理的时候为 #(worker_connections * worker_processes)/2
}
http { #http块是Nginx服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都可以 #在这设置,http块可以包含多个server块,而一个server块中又可以包含多个location块,server块可 #以配置文件引入、MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和单个链接的请求上限等。
include mime.types;
default_type application/octet-stream;
sendfile on; #作为web服务器的时候打开sendfile加快静态文件传输,指定是否使用sendfile系统调用来传 #输文件sendfile系统调用在两个文件描述符之间直接传递数据(完全在内核中操作)从而避免了数 #据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝,硬盘 >> kernel #buffer (快速拷贝到kernel socket buffer) >>协议栈。
keepalive_timeout 65; #长连接超时时间,单位是秒
server { #设置一个虚拟机主机,可以包含自己的全局快,同时也可以包含多个location模块比如本 #虚拟机监听的端口、本虚拟机的名称和IP配置,多个server 可以使用一个端口比如都使用 #80端口提供web服务
listen 80; #配置server监听的端口
server_name localhost; #本server的名称,当访问此名称的时候nginx会调用当前serevr内部的配置进程匹配。
location / { #location其实是server的一个指令,为nginx服务器提供比较多而且灵活的指令都是在 #location中体现的,主要是基于nginx接受到的请求字符串对用户请求的UIL进行匹配,并对特 #定的指令进行处理包括地址重定向、数据缓存和应答控制等功能都是在这部分实现另外很多第三方 #模块的配置也是在location模块中配置。
root html; #相当于默认页面的目录名称,默认是安装目录的相对路径,可以使用绝对路径配置。
index index.html index.htm; #默认的页面文件名称
}
error_page 500 502 503 504 /50x.html; #错误页面的文件名称
location = /50x.html { #location处理对应的不同错误码的页面定义到/50x.html
root html; #定义默认页面所在的目录
}
}
#和邮件相关的配置
#mail {
# ...
# } mail 协议相关配置段
#tcp代理配置,1.9版本以上支持
#stream {
# ...
# } stream 服务器相关配置段
#导入其他路径的配置文件
#include /apps/nginx/conf.d/*.conf
}
3.2 全局配置
Main 全局配置段常见的配置指令分类
-
正常运行必备的配置
-
优化性能相关的配置
-
用于调试及定位问题相关的配置
-
事件驱动相关的配置
全局配置说明:
user nginx nginx; #启动Nginx工作进程的用户和组
worker_processes [number | auto]; #启动Nginx工作进程的数量,一般设为和CPU核心数相同
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
#将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进程独占以一核心CPU,但是可以保证此进程不运行在其他核心上,这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能。
CPU MASK: 00000001:0号CPU
00000010:1号CPU
10000000:7号CPU
#示例
worker_cpu_affinity 0001 0010 0100 1000;第0号---第3号CPU
worker_cpu_affinity 0101 1010;
#错误日志记录配置,语法:error_log file [debug | info | notice | warn | error | crit | alert | emerg]
#error_log logs/error.log;
#error_log logs/error.log notice;
error_log /usr/local/nginx/logs/error.log error;
#pid文件保存路径
pid /usr/local/nginx/logs/nginx.pid;
worker_priority 0; #工作进程优先级,-20~20(19)
worker_rlimit_nofile 65536; #所有worker进程能打开的文件数量上限,
#包括:Nginx的所有连接(例如与代理服务器的连接等)
#而不仅仅是与客户端的连接
#另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数的限制
#最好与ulimit -n 或者limits.conf的值保持一致
#修改pam限制
[root@nginx-node1 ~]# sudo -u nginx ulimit -n
1024
[root@nginx-node1 ~]# vim /etc/security/limits.conf
nginx - nofile 100000
[root@nginx-node1 ~]# sudo -u nginx ulimit -n
100000
daemon off; #前台运行Nginx服务用于测试、docker等环境。
master_process off|on; #是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为on
events {
worker_connections 65535; #设置单个工作进程的最大并发连接数
use epoll; #使用epoll事件驱动,
#Nginx支持众多的事件驱动,
#比如:select、poll、epoll,只能设置在events模块中设置
accept_mutex on; #on为同一时刻一个请求轮流由work进程处理,
#而防止被同时唤醒所有worker
#避免多个睡眠进程被唤醒的设置,默认为off
#新请求会唤醒所有worker进程,此过程也称为"惊群"
#因此nginx刚安装完以后要进行适当的优化。建议设置为on
multi_accept on; #on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接
#此指令默认为off,
#即默认为一个工作进程只能一次接受一个新的网络连接
#打开后几个同接受多个。建议设置为on
}
示例: 实现 nginx 的高并发配置
修改配置
[root@nginx-node1 ~]# vim /etc/security/limits.conf
nginx - nofile 100000
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
....................
events {
worker_connections 100000;
use epoll;
}
....................
[root@nginx-node1 ~]# systemctl restart nginx.service
测试
[root@nginx-node1 ~]# sudo -u nginx ulimit -n
100000
[root@nginx-node1 ~]# yum install -y httpd-tools
[root@nginx-node1 ~]# ab -n 100000 -c 500 http://172.25.254.100/index.html
3.3 http 配置块
#在响应报文中将指定的文件扩展名映射至MIME对应的类型
include /etc/nginx/mime.types;
default_type application/octet-stream; #除mime.types中的类型外
#指定其它文件的默认MIME类型,浏览器一般会提示下载
types {
text/html html;
image/gif gif;
image/jpeg jpg;
}
示例:识别php文件为text/html
[root@nginx-node1 ~]# vim /usr/local/nginx/html/zty.php
<?php
phpinfo();
?>
[root@nginx-node1 ~]# curl -I 172.25.254.100/zty.php
HTTP/1.1 200 OK
Server: zty/1.0
Date: Thu, 15 Aug 2024 13:50:31 GMT
Content-Type: application/octet-stream
Content-Length: 25
Last-Modified: Thu, 15 Aug 2024 13:49:16 GMT
Connection: keep-alive
ETag: "66be075c-19"
Accept-Ranges: bytes
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
.......
default_type text/html;
......
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl -I 172.25.254.100/zty.php
HTTP/1.1 200 OK
Server: zty/1.0
Date: Thu, 15 Aug 2024 13:53:29 GMT
Content-Type: text/html
Content-Length: 25
Last-Modified: Thu, 15 Aug 2024 13:49:16 GMT
Connection: keep-alive
ETag: "66be075c-19"
Accept-Ranges: bytes
3.4 核心配置示例
基于不同的IP、不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块 ngx_http_core_module实现。
3.4.1 新建一个 PC web 站点
定义子配置文件路径
[root@nginx-node1 ~]# mkdir /usr/local/nginx/conf.d/
[root@centos8 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
....................
include /usr/local/nginx/conf.d/*.conf; #在配置文件的最后面添加此行
#注意不要放在最前面,会导致前面的命令无法生效
}
创建虚拟主机网站配置
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com
root /web/html;
index index.html;
}
[root@nginx-node1 ~]# mkdir -p /web/html
[root@nginx-node1 ~]# echo www.zty.com > /web/html/index.html
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.zty.com #注意在访问主机中设解析
www.zty.com
3.4.2 root 与 alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location
root示例:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /web/html;
index index.html;
location /test1 {
root /web/html; #必须建立/web/html/test1才能访问
}
}
[root@nginx-node1 ~]# mkdir /web/html/test1 -p
[root@nginx-node1 ~]# echo /web/html/test1 > /web/html/test1/index.html
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.zty.com/test1/
/web/html/test1
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于location上下文,此指令使用较少
alias示例:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /web/html;
index index.html;
location /test1 {
root /web/html;
}
location /test2 { #注意test2后不要加/
#使用alias的时候uri后面如果加了斜杠,则下面的路径配置必须加斜杠,否则403
alias /web/html/test1; #当访问test的时候,会显示alias定义的/web/html/test1里面的内容
}
}
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.zty.com/test2/
/web/html/test1
location中使用root指令和alias指令的意义不同
root #给定的路径对应于location中的/uri左侧的/ alias #给定的路径对应于location中的/uri的完整路径
3.4.3 location 的详细使用
- 在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;
- ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,
- 而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri
- uri是用户请求的字符串,即域名后面的web文件路径
- 然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。
#语法规则:
location [ = | ~ | ~* | ^~ ] uri { ... }
= #用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求
^~ #用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头
#对uri的最左边部分做匹配检查,不区分字符大小写
~ #用于标准uri前,表示包含正则表达式,并且区分大小写
~* #用于标准uri前,表示包含正则表达式,并且不区分大写
不带符号 #匹配起始于此uri的所有的uri
\ #用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号
#匹配优先级从高到低:
对目录匹配:(~|~*) > 不带符号 > ^~ #=不能指定目录
对文件匹配:= > (~|~*) > 不带符号 > ^~
3.4.3.1 匹配案例-精确匹配
在server部分使用location配置一个web界面,例如:当访问nginx 服务器的/index.html的时候要显示指定 html文件的内容,精确匹配一般用于匹配组织的logo等相对固定的URL,匹配优先级最高
1.精确匹配 index
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location = /test/index.html {
root /date/web3;
}
}
测试
[root@nginx-node1 ~]# curl www.zty.com/test/index.html
web3
3.4.3.2 匹配案例-区分大小写
~ 实现区分大小写的模糊匹配. 以下范例中,
如果访问uri中包含大写字母的inedx.HTML,则以下location匹配index.html条件不成功
因为 ~ 区分大小写,当用户的请求被执行匹配时发现location中定义的是小写的html,
本次访问的uri匹配失败,后续要么继续往下匹配其他的location(如果有),要么报错给客户端
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location ~ .html$ {
root /date/web4;
}
}
测试
[root@nginx-node1 ~]# curl www.zty.com/test/index.html
web4
3.4.3.3 匹配案例-不区分大小写
~* 用来对用户请求的uri做模糊匹配,uri中无论都是大写、都是小写或者大小写混合,此模式也都会匹配,通常使用此模式匹配用户request中的静态资源并继续做下一步操作,此方式使用较多
注意: 此方式中,对于Linux文件系统上的文件仍然是区分大小写的,如果磁盘文件不存在,仍会提示404
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location ~* .HTML$ {
root /date/web5;
}
}
测试
[root@nginx-node1 ~]# curl www.zty.com/test/index.html
web5
3.4.3.4 匹配案例-URI开始
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location ^~ /t {
root /date/web2;
}
}
测试
[root@nginx-node1 ~]# curl www.zty.com/test/
web2
3.4.3.5 匹配案例-文件名后缀
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location ~* .(HTML|gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js|css)$ {
root /date/web5;
}
}
测试
[root@nginx-node1 ~]# curl www.zty.com/test/index.html
web5
3.4.3.6 匹配案例-优先级
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location /test {
root /date/web1;
}
location ^~ /t {
root /date/web2;
}
location = /test/index.html {
root /date/web3;
}
location ~ .html$ {
root /date/web4;
}
location ~* .HTML$ {
root /date/web5;
}
}
匹配优先级:=, ~/~*,^~,/
location优先级:(location =) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 完整路径) > (location 部分起始路径) > (/)
3.4.3.7 生产使用案例
#直接匹配网站根会加速Nginx访问处理
location = /index.html {
......;
}
location / {
......;
}
#静态资源配置方法1
location ^~ /static/ {
......;
}
#静态资源配置方法2,应用较多
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
......;
}
#多应用配置
location ~* /app1 {
......;
}
location ~* /app2 {
......;
}
3.4.4 Nginx 账户认证功能
由 ngx_http_auth_basic_module 模块提供此功能
示例:
[root@nginx-node1 ~]# htpasswd -cmb /usr/local/nginx/conf/.htpasswd admin redhat #-b 表示非交互建立用户认证
Adding password for user admin
[root@nginx-node1 ~]# htpasswd -mb /usr/local/nginx/conf/.htpasswd zty redhat
Adding password for user zty
[root@nginx-node1 ~]# cat /usr/local/nginx/conf/.htpasswd
admin:$apr1$bH7X4yG3$EXMa/IJcyPWBCPF1ak62L/
zty:$apr1$s6S/lD7m$jKCxuN8x3jo7bMsVJg0IO/
[root@nginx-node1 ~]# mkdir /date/web/zty
[root@nginx-node1 ~]# echo zty > /date/web/zty/index.html
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location /zty {
root /date/web;
auth_basic "login password...";
auth_basic_user_file "/usr/local/nginx/conf/.htpasswd";
}
}
[root@nginx-node1 ~]# nginx -s reload
重启Nginx并访问测试
[root@nginx-node1 ~]# curl www.zty.com/zty/ -u zty:redhat
zty
3.4.5 自定义错误页面
自定义错误页,同时也可以用指定的响应状态码进行响应, 可用位置:http, server, location, if in location
error_page code ... [=[response]] uri;
示例:自定义错误页面
[root@nginx-node1 ~]# mkdir /date/web/error -p
[root@nginx-node1 ~]# echo "哈哈,访问不了" > /date/web/error/40x.html
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
error_page 404 /40x.html;
location /40x.html {
root /date/web/error;
}
}
测试
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.zty.com/haha
哈哈,访问不了
3.4.6 自定义错误日志
可以自定义错误日志
Syntax: error_log file [level];
Default:
error_log logs/error.log error;
Context: main, http, mail, stream, server, location
level: debug, info, notice, warn, error, crit, alert, emerg
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
error_page 404 /40x.html;
access_log /var/log/www.zty.com/access.log;
error_log /var/log/www.zty.com/error.log;
........
}
[root@nginx-node1 ~]# mkdir /var/log/www.zty.com/
[root@nginx-node1 ~]# nginx -s reload
测试
[root@nginx-node1 ~]# curl www.zty.com
111
[root@nginx-node1 ~]# cat /var/log/www.zty.com/access.log
172.25.254.100 - - [16/Aug/2024:14:30:23 +0800] "GET / HTTP/1.1" 200 4 "-" "curl/7.76.1"
[root@nginx-node1 ~]# curl www.zty.com/haha
哈哈,访问不了
[root@nginx-node1 ~]# cat /var/log/www.zty.com/error.log
2024/08/16 14:30:40 [error] 2478#0: *56 open() "/date/web/haha" failed (2: No such file or directory), client: 172.25.254.100, server: www.zty.com, request: "GET /haha HTTP/1.1", host: "www.zty.com"
3.4.7 检测文件是否存在
try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如 果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一 个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内 部500错误。
语法格式
Syntax: try_files file ... uri;
try_files file ... =code;
Default: —
Context: server, location
示例: 如果不存在页面, 就转到default.html页面
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
error_page 404 /40x.html;
access_log /var/log/www.zty.com/access.log;
error_log /var/log/www.zty.com/error.log;
try_files $uri $uri.html $uri/index.html /adsent/default.html;
........
}
[root@nginx-node1 web]# mkdir /date/web/adsent
[root@nginx-node1 web]# echo default page > /date/web/adsent/default.html
测试
[root@nginx-node1 web]# curl www.zty.com/haha
default page
3.4.8 长连接配置
keepalive_timeout timeout [header_timeout]; #设定保持连接超时时长,0表示禁止长连接,默认为75s
#通常配置在http字段作为站点全局配置
keepalive_requests 数字; #在一次长连接上所允许请求的资源的最大数量
#默认为100次,建议适当调大,比如:500
keepalive_requests 3;
keepalive_timeout 65 60;
#开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断开,第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时间。
Keep-Alive:timeout=60 #浏览器收到的服务器返回的报文
#如果设置为0表示关闭会话保持功能,将如下显示:
#Connection:close 浏览器收到的服务器返回的报文
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
..........
http {
..........
keepalive_timeout 65 60;
keepalive_requests 2;
...........
使用命令测试:
[root@nginx-node1 ~]# dnf install telnet -y
[root@nginx-node1 ~]# telnet www.zty.com 80
Trying 172.25.254.100...
Connected to www.zty.com.
Escape character is '^]'.
GET / HTTP/1.1 ##输入动作
Host: www.zty.com ##输入访问HOST
##输入回车
HTTP/1.1 200 OK
Server: zty/1.0
Date: Fri, 16 Aug 2024 06:53:37 GMT
Content-Type: text/html
Content-Length: 4
Last-Modified: Fri, 16 Aug 2024 02:41:56 GMT
Connection: keep-alive
Keep-Alive: timeout=60
ETag: "66bebc74-4"
Accept-Ranges: bytes
111
GET / HTTP/1.1 #第二次操作
Host: www.zty.com #第二次操作
#第二次操作
HTTP/1.1 200 OK
Server: zty/1.0
Date: Fri, 16 Aug 2024 06:53:51 GMT
Content-Type: text/html
Content-Length: 4
Last-Modified: Fri, 16 Aug 2024 02:41:56 GMT
Connection: close
ETag: "66bebc74-4"
Accept-Ranges: bytes
111
Connection closed by foreign host. #自动断开链接
3.4.9 作为下载服务器配置
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,同时设置,此项优级高.
示例:实现下载站点
[root@nginx-node1 ~]# mkdir /date/web/download
[root@nginx-node1 ~]#
[root@nginx-node1 ~]# dd if=/dev/zero of=/date/web/download/ztylife bs=1M count=100
记录了100+0 的读入
记录了100+0 的写出
104857600字节(105 MB,100 MiB)已复制,0.0847 s,1.2 GB/s
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
error_page 404 /40x.html;
access_log /var/log/www.zty.com/access.log;
error_log /var/log/www.zty.com/error.log;
try_files $uri $uri.html $uri/index.html /adsent/default.html;
location /download {
root /date/web;
autoindex on; #自动索引功能
autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间,默为为off显示GMT时间
autoindex_exact_size off; #计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb、mb、gb)
limit_rate 1024k; #限速,默认不限速
}
}
重启Nginx并访问测试下载页面
[root@nginx-node1 ~]# curl www.zty.com/download/
<html>
<head><title>Index of /download/</title></head>
<body>
<h1>Index of /download/</h1><hr><pre><a href="../">../</a>
<a href="ztylife">ztylife</a> 16-Aug-2024 15:19 100M
</pre><hr></body>
</html>
[root@nginx-node1 ~]# wget www.zty.com/download/ztylife
--2024-08-16 15:37:25-- http://www.zty.com/download/ztylife
正在解析主机 www.zty.com (www.zty.com)... 172.25.254.100
正在连接 www.zty.com (www.zty.com)|172.25.254.100|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:104857600 (100M) [application/octet-stream]
正在保存至: “ztylife”
ztylife 72%[========================================> ] 72.00M 1.00MB/s 剩余 28s
四、Nginx 高级配置
4.1 Nginx 状态页
基于nginx 模块 ngx_http_stub_status_module 实现,
在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
否则配置完成之后监测会是提示法错误
注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态
#配置示例:
location /nginx_status {
stub_status;
auth_basic "auth login";
auth_basic_user_file /apps/nginx/conf/.htpasswd;
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
#状态页用于输出nginx的基本状态信息:
#输出信息示例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106
Active connections: #当前处于活动状态的客户端连接数
#包括连接等待空闲连接数=reading+writing+waiting
accepts: #统计总值,Nginx自启动后已经接受的客户端请求连接的总数。
handled: #统计总值,Nginx自启动后已经处理完成的客户端请求连接总数
#通常等于accepts,除非有因worker_connections限制等被拒绝的连接
requests: #统计总值,Nginx自启动后客户端发来的总的请求数
Reading: #当前状态,正在读取客户端请求报文首部的连接的连接数
#数值越大,说明排队现象严重,性能不足
Writing: #当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting: #当前状态,正在等待客户端发出请求的空闲连接数开启 keep-alive的情况下,这个值等于 #active – (reading+writing)
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/status.conf
server {
listen 80;
server_name status.zty.com;
root /date/web;
index index.html;
location /status {
stub_status;
allow 172.25.254.1;
deny all;
}
}
[root@nginx-node1 ~]# nginx -s reload
测试
在 172.25.254.100 访问状态页,被禁止访问
[root@nginx-node1 ~]# curl status.zty.com/status/
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>zty/1.0</center>
</body>
</html>
在 172.25.254.1 访问状态页
4.2 Nginx 压缩功能
Nginx支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文件大小将比源文件显著变小,样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相 应的CPU资源。
Nginx对文件的压缩功能是依赖于模块ngx_http_gzip_module,默认是内置模块
配置指令如下
#启用或禁用gzip压缩,默认关闭
gzip on | off;
#压缩比由低到高从1到9,默认为1,值越高压缩后文件越小,但是消耗cpu比较高。基本设定未4或者5
gzip_comp_level 4;
#禁用IE6 gzip功能,早期的IE6之前的版本不支持压缩
gzip_disable "MSIE [1-6]\.";
#gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
#启用压缩功能时,协议的最小版本,默认HTTP/1.1
gzip_http_version 1.0 | 1.1;
#指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 8k;
gzip_buffers number size;
#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
gzip_types mime-type ...;
#如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开
gzip_vary on | off;
#预压缩,即直接从磁盘找到对应文件的gz后缀的式的压缩文件返回给用户,无需消耗服务器CPU
#注意: 来自于ngx_http_gzip_static_module模块
gzip_static on | off;
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
...............
http {
...............
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/gif image/png;
gzip_vary on;
[root@nginx-node1 ~]# echo small > /date/web/small.html
[root@nginx-node1 ~]# cp /usr/local/nginx/logs/access.log /date/web/big.html
[root@nginx-node1 ~]# du -sh /date/web/big.html
54M /date/web/big.html
测试
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl --head --compressed www.zty.com/small.html
HTTP/1.1 200 OK
Server: zty/1.0
Date: Fri, 16 Aug 2024 08:22:51 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Fri, 16 Aug 2024 08:21:17 GMT
Connection: keep-alive
Keep-Alive: timeout=60
ETag: "66bf0bfd-6"
Accept-Ranges: bytes #未被压缩
[root@nginx-node1 ~]# curl --head --compressed www.zty.com/big.html
HTTP/1.1 200 OK
Server: zty/1.0
Date: Fri, 16 Aug 2024 08:22:53 GMT
Content-Type: text/html
Last-Modified: Fri, 16 Aug 2024 08:19:23 GMT
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding
ETag: W/"66bf0b8b-351c0eb"
Content-Encoding: gzip #被压缩
4.3 Nginx的版本隐藏
用户在访问nginx的时候,我们可以从报文中获得nginx的版本,相对于裸漏版本号的nginx,我们把其隐藏起来更安全
[root@nginx-node1 objs]# vim /root/nginx-1.24.0/src/core/nginx.h
....................
#define nginx_version 1024000
#define NGINX_VERSION "1.0"
#define NGINX_VER "zty/" NGINX_VERSION
....................
4.4 Nginx 变量使用
nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
变量可以分为内置变量和自定义变量
内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值
4.4.1 内置变量
官方文档:http://nginx.org/en/docs/varindex.html
常用内置变量
$remote_addr;
#存放了客户端的地址,注意是客户端的公网IP
$args;
#变量中存放了URL中的所有参数
#例如:https://search.jd.com/Search?keyword=手机&enc=utf-8
#返回结果为: keyword=手机&enc=utf-8
$is_args
#如果有参数为? 否则为空
$document_root;
#保存了针对当前资源的请求的系统根目录,例如:/webdata/nginx/timinglee.org/lee。
$document_uri;
#保存了当前请求中不包含参数的URI,注意是不包含请求的指令
#比如:http://lee.timinglee.org/var?\id=11111会被定义为/var
#返回结果为:/var
$host;
#存放了请求的host名称
limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_port;
#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口
$remote_user;
#已经经过Auth Basic Module验证的用户名
$request_body_file;
#做反向代理时发给后端服务器的本地资源的名称
$request_method;
#请求资源的方式,GET/PUT/DELETE等
$request_filename;
#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,
#如:webdata/nginx/timinglee.org/lee/var/index.html
$request_uri;
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,
#例如:/main/index.do?id=20190221&partner=search
$scheme;
#请求的协议,例如:http,https,ftp等
$server_protocol;
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr;
#保存了服务器的IP地址
$server_port;
#虚拟主机的端口号
$http_user_agent;
#客户端浏览器的详细信息
$http_cookie;
#客户端的所有cookie信息
$cookie_<name>
#name为任意请求报文首部字部cookie的key名
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有横线需要替换为下划线
#示例:
echo $http_user_agent;
echo $http_host;
$sent_http_<name>
#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有问题
echo $sent_http_server;
$arg_<name>
#此变量存放了URL中的指定参数,name为请求url中指定的参数
echo $arg_id;
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.zty.com;
root /data/web;
index index.html;
location /var {
default_type text/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;
}
}
测试
[root@nginx-node1 ~]# curl -b "key1=zty1,key2=zty2" -u lee:lee var.zty.com/var?name=zty&&id=6666
172.25.254.100
name=zty
?
/data/web
/var
var.zty.com
50726
lee
GET
/data/web/var
/var?name=zty
http
HTTP/1.1
172.25.254.100
var.zty.com
80
curl/7.76.1
key1=zty1,key2=zty2
zty2
4.4.2 自定义变量
假如需要自定义变量名称和值,使用指令set $variable value;
语法格式:
Syntax: set $variable value;
Default: —
Context: server, location, if
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.zty.com;
root /data/web;
index index.html;
location /var2 {
default_type text/html;
set $test ztyzty;
echo $test;
}
}
测试
[root@nginx-node1 ~]# curl var.zty.com/var2/
ztyzty
五、Nginx Rewrite 相关功能
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
另外还可以在一定程度上提高网站的安全性。
5.1 ngx_http_rewrite_module 模块指令
官方文档: https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
5.1.1 if 指令
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:
if (条件匹配) {
action
}
使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接:
= #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!= #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~ #区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ #区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~* #不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* #不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)
#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /data/web;
index index.html;
location /test2 {
if ( !-e $request_filename ){
echo "$request_filename is not exist";
}
}
}
测试
[root@nginx-node1 ~]# curl rw.zty.com/if/
/data/web/if/ is not exist
5.1.2 set 指令
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key
另外set定义格式为set $key value,value可以是text, variables和两者的组合。
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /data/web;
index index.html;
location /set {
default_type text/html;
set $name zty;
echo $name;
}
}
测试
[root@nginx-node1 ~]# curl rw.zty.com/set/
zty
5.1.3 break 指令
用于中断当前相同作用域(location)中的其他Nginx配置
与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置
该指令可以在server块和locationif块中使用
注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /data/web;
index index.html;
location /break {
default_type text/html;
set $name zty;
echo $name;
if ( $http_user_agent = "curl/7.76.1" ){
break;
}
set $id 666;
echo $id;
}
}
测试
[root@nginx-node1 ~]# curl rw.zty.com/break
zty
[root@nginx-node1 ~]# curl -A "360" rw.zty.com/break
zty
666
5.1.4 return 指令
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置
语法格式:
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容
#可以调用变量,其中text如果有空格,需要用单或双引号
return code URL; #返回给客户端的URL地址
示例
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
server {
listen 80;
server_name rw.zty.com;
root /data/web;
index index.html;
location /return {
default_type text/html;
if ( !-e $request_filename){
return 301 http://www.baidu.com;
}
echo "$request_filename is exist";
}
}
测试
[root@nginx-node1 web]# curl -I rw.zty.com/return
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 04:09:54 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.baidu.com
[root@nginx-node1 web]# mkdir -p /date/web/return
[root@nginx-node1 web]# curl -I rw.zty.com/return
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 04:12:33 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding
5.2 rewrite 指令
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配 rewrite主要是针对用户请求的URL或者是URI做具体处理
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
语法格式 :
rewrite regex replacement [flag];
rewrite将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI
注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的标志位用于控制此循环机制
如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301
正则表达式格式:
. #匹配除换行符以外的任意字符
\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 #匹配不是单词开头或结束的位置
[^x] #匹配除了x以外的任意字符
[^lee] #匹配除了magedu 这几个字母以外的任意字符
5.2.1 rewrite flag 使用介绍
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型
-
跳转型指由客户端浏览器重新对新地址进行请求
-
代理型是在WEB服务器内部实现跳转
rewrite 格式
Syntax: rewrite regex replacement [flag]; #通过正则表达式处理用户请求并返回替换后的数据包。
Default: —
Context: server, location, if
flag 说明
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作
#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,
#而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
5.2.2 rewrite案例: 域名永久与临时重定向
域名的临时的调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳转,这种情况浏览器不会缓存跳转,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。
5.2.2.1 永久重定向301
域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录可以缓存到客户端浏览器
永久重定向会缓存DNS解析记录, 浏览器中有 from disk cache 信息,即使nginx服务器无法访问,浏览器也会利用缓存进行重定向
比如: 京东早期的域名 www.360buy.com 由于与360公司类似,于是后期永久重定向到了 www.jd.com
示例
[root@nginx-node1 web]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /date/web;
index index.html;
location / {
root /data/web;
index index.html;
rewrite / http://www.zty.com permanent;
#rewrite / http://www.zty.com redirect;
}
}
测试
[root@nginx-node1 web]# curl -I rw.zty.com
HTTP/1.1 301 Moved Permanently #永久重定向301
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 05:19:54 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.zty.com
5.2.2.2 临时重定向302
域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器不会缓存当前域名的解析记录,而浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最大的本质区别。
即当nginx服务器无法访问时,浏览器不能利用缓存,而导致重定向失败
示例
[root@nginx-node1 web]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /date/web;
index index.html;
location / {
root /data/web;
index index.html;
#rewrite / http://www.zty.com permanent;
rewrite / http://www.zty.com redirect;
}
}
测试
[root@nginx-node1 web]# curl -I rw.zty.com
HTTP/1.1 302 Moved Temporarily #临时重定向302
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 05:23:24 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.zty.com
5.2.3 rewrite 案例: break 与 last
测试访问break请求被rewrite至test1,而访问test1转递请求再次被rewrite发送至test2,此测试last和break 分别有什么区别
break和last区别案例
[root@nginx-node1 web]# mkdir /date/web/{test1,test2,break,last} -p
[root@nginx-node1 web]# echo test1 > /date/web/test1/index.html
[root@nginx-node1 web]# echo test2 > /date/web/test2/index.html
[root@nginx-node1 web]# echo break > /date/web/break/index.html
[root@nginx-node1 web]# echo last > /date/web/last/index.html
[root@nginx-node1 web]# vim /usr/local/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name rw.zty.com;
root /date/web;
index index.html;
location /break {
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1;
}
location /last {
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1;
}
location /test1 {
default_type text/html;
set $name hahahaha;
echo $name;
}
location /test2 {
}
}
测试
[root@nginx-node1 web]# curl rw.zty.com/break/index.html
test1
[root@nginx-node1 web]# curl rw.zty.com/last/index.html
hahahaha
5.2.4 rewrite案例: 自动跳转 https
案例:基于通信安全考虑公司网站要求全站 https,因此要求将在不影响用户请求的情况下将http请求全部自动跳转至 https,另外也可以实现部分 location 跳转
[root@nginx-node1 web]# mkdir /usr/local/nginx/certs
[root@nginx-node1 web]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/www.zty.com.key -x509 -days 365 -out /usr/local/nginx/certs/www.zty.com.crt
[root@nginx-node1 web]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
listen 443 ssl;
server_name www.zty.com;
root /date/web/;
index index.html;
ssl_certificate /usr/local/nginx/certs/timinglee.org.crt;
ssl_certificate_key /usr/local/nginx/certs/timinglee.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
if ( $scheme = http ){
rewrite /(.*) https://$host/$1 redirect;
}
}
}
测试
[root@nginx-node1 web]# curl -ikL www.zty.com
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 06:56:51 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Keep-Alive: timeout=60
Location: https://www.zty.com/
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Sun, 18 Aug 2024 06:56:51 GMT
Content-Type: text/html
Content-Length: 4
Last-Modified: Fri, 16 Aug 2024 02:41:56 GMT
Connection: keep-alive
Keep-Alive: timeout=60
ETag: "66bebc74-4"
Accept-Ranges: bytes
111
5.2.5 rewrite 案例: 判断文件是否存在
案例:当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页
[root@nginx-node1 web]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
listen 443 ssl;
server_name www.zty.com;
root /date/web/;
index index.html;
ssl_certificate /usr/local/nginx/certs/timinglee.org.crt;
ssl_certificate_key /usr/local/nginx/certs/timinglee.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
if ( $scheme = http ){
rewrite /(.*) https://$host/$1 redirect;
}
if ( !-e $request_filename ){
rewrite /(.*) https://$host/index.html redirect; #实现客户端浏览器的302跳转
}
}
}
测试
在浏览器访问不存在的url
自动跳转到首页
5.3 Nginx 防盗链
防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名,正常的referer信息有以下几种:
none: #请求报文首部没有referer首部,
#比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked: #请求报文有referer首部,但无有效值,比如为空。
server_names: #referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: #自定义指定字符串,但可使用*作通配符。示例: *.timinglee.org www.timinglee.*
regular expression: #被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.timinglee\.com
5.3.1 实现盗链
在一个web 站点盗链另一个站点的资源信息,比如:图片、视频等
实验环境准备
[root@nginx-node1 images]# ll /date/web/images/logo.jpg
-rw-r--r-- 1 root root 55705 8月 18 15:15 /date/web/images/logo.jpg
[root@nginx-node1 web]# ll /date/web/daolian.jpg
-rw-r--r-- 1 root root 192088 8月 18 16:00 /date/web/daolian.jpg
新建一个主机172.25.254.10,盗取另一台主机www.zty.com/images/logo.png的图片
[root@daolian ~]# yum install -y httpd
[root@daolian ~]# 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.zty.com/images/logo.jpg" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.zty.com>点点点</a>lianjie</p>
</body>
</html>
重启apache并访问172.25.254.10 测试
5.3.2 实现防盗链
基于访问安全考虑,nginx支持通过ngx_http_referer_module模块,检查访问请求的referer信息是否有效 实现防盗链功能
官方文档: https://nginx.org/en/docs/http/ngx_http_referer_module.html
示例 定义防盗链:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.zty.com;
root /date/web/;
index index.html;
location /images {
valid_referers none blocked server_names *.zty.com ~\.baidu\.;
if ( $invalid_referer ){
#return 403;
rewrite ^/ http://www.zty.com/daolian.jpg;
}
}
}
重启Nginx并访问测试 172.25.254.10 看到图片已被替换
六、Nginx 反向代理功能
反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
Nginx 除了可以在企业提供高性能的web服务之外,另外还可以将 nginx 本身不具备的请求通过某种预定义的协议转发至其它服务器处理,不同的协议就是Nginx服务器与其他服务器进行通信的一种规范,主要在不同的场景使用以下模块实现不同的功能
ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass
#等指令引用的后端服务器分组
ngx_stream_proxy_module: #将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module: #将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理
逻辑调用关系:
访问逻辑图:
同构代理:用户不需要其他程序的参与,直接通过http协议或者tcp协议访问后端服务器
异构代理:用户访问的资源时需要经过处理后才能返回的,比如php,python,等等,这种访问资源需要经过处理才能被访问
6.1 实现 http 反向代理
官方文档: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
6.1.1 http 协议反向代理
6.1.1.1 反向代理配置参数
#官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
proxy_pass; #用来设置将客户端请求转发给的后端服务器的主机
#可以是主机名(将转发至后端服务做为主机头首部)、IP地址:端口的方式
#也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module支持
#示例:
location /web {
index index.html;
proxy_pass http://172.25.254.30:8080; #8080后面无uri,即无 / 符号
#需要将location后面url 附加到proxy_pass指定的url后面
#此行为类似于root
#proxy_pass指定的uri不带斜线将访问的/web
#等于访问后端服务器
proxy_pass http://172.25.254.40:8080/; #8080后面有uri,即有 / 符号
#相当于置换,即访问/web时实际返回proxy_pass后面uri内容
#此行为类似于alias
#proxy_pass指定的uri带斜线
#等于访问后端服务器的
#http://172.25.254.40:8080/index.html
#内容返回给客户端
} # http://nginx/web/index.html ==> http://1:8080
#如果location定义其uri时使用了正则表达式模式(包括~,~*,但不包括^~),则proxy_pass之后必须不能使用uri
#即不能有/ ,用户请求时传递的uri将直接附加至后端服务器之后
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy_pass http://host:port; #proxy_pass后面的url 不能加/
}
...
}
http://HOSTNAME/uri/ --> http://host/uri/
proxy_hide_header field; #用于nginx作为反向代理的时候
#在返回给客户端http响应时
#隐藏后端服务器相应头部的信息
#可以设置在http,server或location块
#示例: 隐藏后端服务器ETag首部字段
location /web {
index index.html;
proxy_pass http://10.0.0.18:8080/;
proxy_hide_header ETag;
}
proxy_pass_header field; #透传
#默认nginx在响应报文中不传递后端服务器的首部字段Date, Server, X-Pad, X-Accel等参数
#如果要传递的话则要使用 proxy_pass_header field声明将后端服务器返回的值传递给客户端
#field 首部字段大小不敏感
#示例:透传后端服务器的Server和Date首部给客户端,同时不再响应报中显示前端服务器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
proxy_pass_request_body on | off;
#是否向后端服务器发送HTTP实体部分,可以设置在http,server或location块,默认即为开启
proxy_pass_request_headers on | off;
#是否将客户端的请求头部转发给后端服务器,可以设置在http,server或location块,默认即为开启
proxy_set_header;
#可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实IP的时候,就要更改每一个报文的头部
#示例:
location ~ /web {
proxy_pass http://172.25.254.20:80;
proxy_hide_header ETag;
proxy_pass_header Server;
proxy_pass_request_body on;
proxy_pass_request_headers on;
proxy_set_header X-Forwarded-For $remote_addr;
}
[root@apache20 ~]# vim /etc/httpd/conf/httpd.conf
LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
访问后看后端服务器日志
proxy_connect_timeout time;
#配置nginx服务器与后端服务器尝试建立连接的超时时间,默认为60秒
用法如下:proxy_connect_timeout 6s;
#60s为自定义nginx与后端服务器建立连接的超时时间,超时会返回客户端504响应码
proxy_read_timeout time;
#配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认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.1.1.2 实战案例: 反向代理单台 web 服务器
要求:将用户对域 www.zty.org 的请求转发给后端服务器处理
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.zty.org;
location / {
proxy_pass http://172.25.254.10;
}
}
重启Nginx 并访问测试
[C:\~]$ curl www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1223 0 --:--:-- --:--:-- --:--:-- 2333
172.25.254.10
6.1.1.3 实战案例: 指定 location 实现反向代理
6.1.1.3.1 针对指定的 location
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.zty.org;
location / {
proxy_pass http://172.25.254.10:80;
}
location ~ /static {
proxy_pass http://172.25.254.20:80;
}
}
后端web服务器必须要有相对于的访问URL
[root@web20 ~]# mkdir /var/www/html/static
[root@web20 ~]# echo static 172.25.254.20 > /var/www/html/static/inedx,html
重启Nginx并访问测试
[C:\~]$ curl www.zty.org/static/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 21 100 21 0 0 2193 0 --:--:-- --:--:-- --:--:-- 3500
static 172.25.254.20
[C:\~]$ curl www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1450 0 --:--:-- --:--:-- --:--:-- 2800
172.25.254.10
6.1.1.3.2 针对特定的资源实现代理
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.zty.org;
location ~.php$ {
proxy_pass http://172.25.254.10:80;
}
location ~ /static {
proxy_pass http://172.25.254.20:80;
}
}
后端web服务器必须要有相对于的访问URL
[root@web10 ~]# echo I am php > /var/www/html/index.php
测试
[C:\~]$ curl www.zty.org/index.php
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 9 100 9 0 0 942 0 --:--:-- --:--:-- --:--:-- 1500
I am php
[C:\~]$ curl www.zty.org/static/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 21 100 21 0 0 2009 0 --:--:-- --:--:-- --:--:-- 3500
static 172.25.254.20
6.1.1.4 反向代理示例: 缓存功能
缓存功能默认关闭状态,需要先动配置才能启用
proxy_cache zone_name | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义
proxy_cache_key string;
#缓存中用于“键”的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code ...] time;
#定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_path;
#定义可用于proxy功能的缓存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off]
keys_zone=zone_name:size [inactive=time] [max_size=size] [manager_files=number]
[manager_sleep=time] [manager_threshold=time] [loader_files=number]
[loader_sleep=time] [loader_threshold=time] [purger=on|off]
[purger_files=number] [purger_sleep=time] [purger_threshold=time];
#示例:在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2 #定义缓存目录结构层次
#1:2:2可以生成2^4x2^8x2^8=2^20=1048576个目录
keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata(如:使用次数)
#一般1M可存放8000个左右的key
inactive=120s #缓存有效时间
max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
#调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置,否则不会缓存
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; #默认是off
#在被代理的后端服务器出现哪种情况下,可直接使用过期的缓存响应客户端
#示例
proxy_cache_use_stale error http_502 http_503;
proxy_cache_methods GET | HEAD | POST ...;
#对哪些客户端请求方法对应的响应进行缓存,GET和HEAD方法总是被缓存
非缓存场景压测
[root@web10 ~]# ab -n1000 -c100 http://www.zty.org/static/index.html
Concurrency Level: 100
Time taken for tests: 0.216 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 272000 bytes
HTML transferred: 21000 bytes
Requests per second: 4633.19 [#/sec] (mean)
Time per request: 21.583 [ms] (mean)
Time per request: 0.216 [ms] (mean, across all concurrent requests)
Transfer rate: 1230.69 [Kbytes/sec] received
准备缓存配置
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
.........
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g; #配置在nginx.conf http配置段
.........
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/pc.conf
server {
listen 80;
server_name www.zty.org;
location ~.php$ {
proxy_pass http://172.25.254.10:80;
}
location ~ /static { #要缓存的URL 或者放在server配置项对所有URL都进行缓存
proxy_pass http://172.25.254.20:80;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m; #必须指定哪些响应码的缓存
}
}
/usr/local/nginx/proxycache/ 目录会自动生成
[root@nginx-node1 nginx]# ll -d /usr/local/nginx/proxy_cache/
drwx------ 2 nginx root 6 8月 18 20:51 /usr/local/nginx/proxy_cache/
[root@nginx-node1 nginx]# tree /usr/local/nginx/proxy_cache/
/usr/local/nginx/proxy_cache/
0 directories, 0 files
访问并验证缓存文件
访问web并验证缓存目录
[root@web10 ~]# ab -n1000 -c100 http://www.zty.org/static/index.html
Concurrency Level: 100
Time taken for tests: 0.104 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 272000 bytes
HTML transferred: 21000 bytes
Requests per second: 9657.36 [#/sec] (mean)
Time per request: 10.355 [ms] (mean)
Time per request: 0.104 [ms] (mean, across all concurrent requests)
Transfer rate: 2565.24 [Kbytes/sec] received
验证缓存目录结构及文件大小
[root@nginx-node1 nginx]# tree /usr/local/nginx/proxy_cache/
/usr/local/nginx/proxy_cache/
└── e
└── 50
└── 99
└── 319432ef3663735a9d3cb4e0c1d9950e
3 directories, 1 file
6.1.2 http 反向代理负载均衡
在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能
官方文档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
6.1.2.1 http upstream配置参数
#自定义一组服务器,配置在http块内
upstream name {
server .....
......
}
#示例
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失 #败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非 #周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复 #可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down #标记为down状态,可以平滑下线后端服务器
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
hash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid #基于cookie中的sessionid这个key进行hash调度,实现会话绑定
ip_hash; #源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做 #hash计算,以实现会话保持
least_conn; #最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC
6.1.2.2 反向代理示例: 后端多台 web服务器
环境说明:
172.25.254.100 #Nginx 代理服务器
172.25.254.10 #后端web A,Apache部署
172.25.254.20 #后端web B,Apache部署
部署后端 Apache服务器
[root@web10 ~]# yum install httpd -y
[root@web10 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@web10 ~]# systemctl enable --now 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@nginx-node1 nginx]# curl 172.25.254.10
172.25.254.10
[root@nginx-node1 nginx]# curl 172.25.254.20
172.25.254.20
配置 nginx 反向代理
注意: 本节实验过程中先关闭缓存
[root@nginx-node1 nginx]# vim /usr/local/nginx/conf.d/pc.conf
upstream webserver {
#ip_hash;
#hash $request_uri consistent;
#hash $cookie_zty;
#least_conn;
server 172.25.254.10:80 fail_timeout=15s max_fails=3;
server 172.25.254.20:80 fail_timeout=15s max_fails=3;
server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.zty.org;
location / {
proxy_pass http://webserver;
}
}
重启Nginx 并访问测试
[C:\~]$ curl www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1461 0 --:--:-- --:--:-- --:--:-- 2333
172.25.254.10
[C:\~]$ curl www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1503 0 --:--:-- --:--:-- --:--:-- 2800
172.25.254.20
实战案例: 基于Cookie 实现会话绑定
[root@nginx-node1 nginx]# vim /usr/local/nginx/conf.d/pc.conf
upstream webserver {
#ip_hash;
#hash $request_uri consistent;
hash $cookie_zty;
#least_conn;
server 172.25.254.10:80 fail_timeout=15s max_fails=3;
server 172.25.254.20:80 fail_timeout=15s max_fails=3;
#server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.zty.org;
location / {
proxy_pass http://webserver;
}
}
测试
[C:\~]$ curl -b zty=1 www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1397 0 --:--:-- --:--:-- --:--:-- 2333
172.25.254.10
[C:\~]$ curl -b zty=1 www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 866 0 --:--:-- --:--:-- --:--:-- 1166
172.25.254.10
[C:\~]$ curl -b zty=2 www.zty.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1518 0 --:--:-- --:--:-- --:--:-- 2800
172.25.254.20
6.2 实现 Nginx 四层负载均衡
Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用 DNS的域名解析,其配置方式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等高级功能。
如果编译安装,需要指定 --with-stream 选项才能支持ngx_stream_proxy_module模块
官方文档: https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html
6.2.1 tcp负载均衡配置参数
stream { #定义stream相关的服务;
Context:main
upstream backend { #定义后端服务器
hash $remote_addr consistent; #定义调度算法
server backend1.example.com:12345 weight=5; #定义具体server
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}
upstream dns { #定义后端服务器
server 10.0.0.1:53; #定义具体server
server dns.example.com:53;
}
server { #定义server
listen 12345; #监听IP:PORT
proxy_connect_timeout 1s; #连接超时时间
proxy_timeout 3s; #转发超时时间
proxy_pass backend; #转发到具体服务器组
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}
6.2.2 负载均衡实例: MySQL
后端服务器安装 MySQL
[root@web10 ~]# yum install mariadb-server -y
[root@web10 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=10
[root@web10 ~]# systemctl start mariadb
[root@web10 ~]# mysql -e "grant all on *.* to zty@'%' identified by 'redhat';"
[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 zty@'%' identified by 'redhat';"
nginx配置
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
include "/usr/local/nginx/tcpconf.d/*.conf"; #在http配置段外,添加子配置目录
[root@nginx-node1 ~]# mkdir /usr/local/nginx/tcpconf.d -p
[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/tcp.conf
stream {
upstream mysql_server {
server 172.25.254.10:3306 max_fails=3 fail_timeout=30s;
server 172.25.254.20:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.100:3306;
proxy_pass mysql_server;
proxy_connect_timeout 30s;
proxy_timeout 300s;
}
}
重启nginx并访问测试
测试通过nginx负载连接MySQL
[root@nginx-node1 ~]# yum install mariadb -y
[root@nginx-node1 ~]# mysql -uzty -predhat -h172.25.254.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 10 |
+-------------+
[root@nginx-node1 ~]# mysql -uzty -predhat -h172.25.254.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
6.2.3 udp 负载均衡实例: DNS
后端服务器安装 bind
[root@web10 ~]# yum install -y bind
[root@web10 named]# vim /etc/named.rfc1912.zones
zone "zty.org" IN {
type master;
file "zty.org.zone";
allow-update { none; };
};
[root@web10 named]# /var/named/zty.org.zone
$TTL 1D
@ IN SOA ns.zty.org roor.zty.org. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns.zty.org.
ns A 172.25.254.10
www A 172.25.254.10
[root@web10 named]# systemctl start named
[root@web10 named]# dig www.zty.org @172.25.254.10 #测试
.....
;; ANSWER SECTION:
www.zty.org. 86400 IN A 172.25.254.10
.....
在web20重复以上步骤并测试
nginx配置
[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/tcp.conf
stream {
upstream dns_server{
server 172.25.254.10:53 max_fails=3 fail_timeout=30s;
server 172.25.254.20:53 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.100:53 udp;
proxy_pass dns_server;
proxy_timeout 1s;
proxy_responses 1;
error_log logs/dns.log; # 使用UDP协议时,设置代理服务器响应客户端期望的数据报文数
# 该值作为会话的终止条件
}
}
测试
[root@nginx-node1 ~]# dig www.zty.org @172.25.254.100
; <<>> DiG 9.16.23-RH <<>> www.zty.org @172.25.254.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32679
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 8ff5627a03bd84090100000066c2182ed4d4af30bd2bf59a (good)
;; QUESTION SECTION:
;www.zty.org. IN A
;; ANSWER SECTION:
www.zty.org. 86400 IN A 172.25.254.10
;; Query time: 1 msec
;; SERVER: 172.25.254.100#53(172.25.254.100)
;; WHEN: Sun Aug 18 23:50:06 CST 2024
;; MSG SIZE rcvd: 84
[root@nginx-node1 ~]# dig www.zty.org @172.25.254.100
; <<>> DiG 9.16.23-RH <<>> www.zty.org @172.25.254.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15849
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 9d9e08719b0ca0d20100000066c2182f5cc58eb48e7183c4 (good)
;; QUESTION SECTION:
;www.zty.org. IN A
;; ANSWER SECTION:
www.zty.org. 86400 IN A 172.25.254.20
;; Query time: 2 msec
;; SERVER: 172.25.254.100#53(172.25.254.100)
;; WHEN: Sun Aug 18 23:50:07 CST 2024
;; MSG SIZE rcvd: 84
6.3 实现 FastCGI
CGI的由来:
最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技术,比如像php(1995年)、java(1995)、python(1991)语言开发的网站,但是nginx/apache服务器并不能直接运行 php、java这样的文件,apache实现的方式是打补丁,但是nginx缺通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx并回收进程,最后nginx在返回给客户端,那这个约定就是通用网关接口(common gateway interface,简称CGI),CGI(协议) 是web服务器和外部应用程序之间的接口标准,是cgi程序和web服务器之间传递信息的标准化接口。
为什么会有FastCGI?
CGI协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server 每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI进程都会执行这些操作,所以效率很低,而FastCGI是用来提高CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。
什么是PHP-FPM?
PHP-FPM(FastCGI Process Manager:
-
FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
-
进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server 的请求
-
worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
6.3.1 FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理,其配置指令如下:
fastcgi_pass address:port;
#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in location
fastcgi_index name;
#fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
Nginx默认配置示例:
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为
prefix/conf
}
6.3.2 FastCGI实战案例 : Nginx与php-fpm在同一服务器
编译安装更方便自定义参数或选项,所以推荐大家使用源码编译
官方网站:www.php.net
准备 nginx 环境
[root@nginx-node1 ~]# nginx -V
nginx version: nginx/1.26.1
built by gcc 11.4.1 20230605 (Red Hat 11.4.1-2) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --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_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33
源码编译php
利用yum解决php依赖
[root@nginx-node1 ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel
[root@nginx-node1 ~]# yum -y install oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
解压源码并安装
[root@nginx-node1 ~]# tar zxf php-8.3.9.tar.gz
[root@nginx-node1 ~]# cd php-8.3.9/
[root@nginx-node1 php-8.3.9]# ./configure \
--prefix=/usr/local/php \ #安装路径
--with-config-file-path=/usr/local/php/etc \ #指定配置路径
--enable-fpm \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cgi
[root@nginx-node1 ~]# make && make install
php相关配置优化
[root@Nginx-node1 ~]# cd /usr/local/php/etc
[root@Nginx-node1 etc]# cp php-fpm.conf.default php-fpm.conf
[root@Nginx-node1 etc]# vim php-fpm.conf
去掉注释
pid = run/php-fpm.pid #指定pid文件存放位置
[root@nginx-node1 etc]# cd php-fpm.d/
[root@nginx-node1 php-fpm.d]# cp www.conf.default www.conf
生成主配置文件
[root@nginx-node1 php-fpm.d]# cd /root/php-8.3.9/
[root@nginx-node1 php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@nginx-node1 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 #修改时区
生成启动文件
[root@nginx-node1 php-8.3.9]# cd /root/php-8.3.9/
[root@nginx-node1 php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
[root@nginx-node1 ~]# 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@nginx-node1 ~]# systemctl daemon-reload
[root@nginx-node1 ~]# systemctl start php-fpm.service
[root@nginx-node1 ~]# netstat -antlupe | grep php
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 0 118086 141495/php-fpm: mas
添加php环境变量
[root@nginx-node1 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin:/usr/loacl/php/bin:/usr/local/php/sbin
[root@nginx-node1 ~]# source ~/.bash_profile
准备php测试页面
[root@nginx-node1 ~]# mkdir -p /data/php
[root@nginx-node1 ~]# vim /data/php
[root@nginx-node1 ~]# vim /data/php/index.php
<?php
phpinfo();
?>
Nginx配置转发
Nginx安装完成之后默认生成了与fastcgi的相关配置文件,一般保存在nginx的安装路径的conf目录当中,比如/usr/local/nginx/conf/fastcgi.conf、/usr/local/nginx/conf/fastcgi_params。
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/php.conf
server {
listen 80;
server_name www.zty.org;
root /data/php;
index index.html;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
#重启Nginx并访问web测试
[root@Nginx-node1 ~]# nginx -s reload
访问验证php测试页面
6.3.3 php的动态扩展模块(php的缓存模块)
软件下载:http://pecl.php.net/package/memcache
安装memcache模块
[root@Nginx-node1 ~]# tar zxf memcache-8.2.tgz
[root@Nginx-node1 ~]# cd memcache-8.2/
[root@Nginx-node1 memcache-8.2]# yum install autoconf
[root@nginx-node1 memcache-8.2]# phpize
Configuring for:
PHP Api Version: 20230831
Zend Module Api No: 20230831
Zend Extension Api No: 420230831
[root@nginx-node1 memcache-8.2]# ./configure && make && make install
[root@nginx-node1 memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
memcache.so opcache.so
复制测试文件到nginx发布目录中
[root@nginx-node1 ~]# cd memcache-8.2/
[root@nginx-node1 memcache-8.2]# cp example.php memcache.php /data/php/
[root@nginx-node1 memcache-8.2]# vim /data/php/memcache.php
.....
define('ADMIN_USERNAME','zty'); // Admin Username
define('ADMIN_PASSWORD','redhat'); // 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
配置php加载memcache模块
[root@Nginx-node1 ~]# vim /usr/local/php/etc/php.ini
;extension=zip
extension=memcache #添加memcache模块
;zend_extension=opcache
[root@nginx-node1 ~]# systemctl reload php-fpm.service
[root@nginx-node1 ~]# php -m | grep mem
memcache
部署memcached
[root@nginx-node1 ~]# yum install -y memcached
[root@nginx-node1 ~]# systemctl enable --now memcached.service
[root@nginx-node1 ~]# netstat -antlupe | grep memcache
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN 978 141860 147904/memcached
[root@nginx-node1 ~]# vim /etc/sysconfig/memcached
ORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"
测试
访问 http://www.zty.org/example.php 不断刷新
访问 http://www.zty.org/memcache.php 查看命中效果
性能对比
[root@nginx-node1 ~]# ab -n5000 -c10 http://www.zty.org/index.php
.....
Concurrency Level: 10
Time taken for tests: 0.952 seconds
Complete requests: 5000
Failed requests: 490
(Connect: 0, Receive: 0, Length: 490, Exceptions: 0)
....
[root@nginx-node1 ~]# ab -n5000 -c10 http://www.zty.org/example.php
.....
Concurrency Level: 10
Time taken for tests: 1.377 seconds
Complete requests: 5000
Failed requests: 0
.....
6.3.4 php高速缓存
部署方法
在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所以nginx需要重新编译
[root@Nginx-node1 ~]# rm -fr /usr/local/nginx/
[root@Nginx-node1 ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@Nginx-node1 ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@Nginx-node1 ~]# cd nginx-1.26.1/
[root@Nginx-node1 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-module0.33
[root@Nginx-node1 nginx-1.26.1]# make && make install
nginx 配置
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/php.conf
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name www.zty.org;
root /data/php;
index index.html;
location /memc {
internal;
memc_connect_timeout 100ms; #与memcached服务器建立连接的超时时间
memc_send_timeout 100ms; #设置发送请求到memcached服务器的超时时间
memc_read_timeout 100ms; #定义从memcached服务器读取响应超时时间
set $memc_key $query_string; #使用内置变量$query_string来作为key
set $memc_exptime 300; #缓存失效时间300秒
memc_pass memcache; #指定memcached服务器地址
}
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;
}
}
重启nginx后 测试
[root@nginx-node1 ~]# ab -n5000 -c10 http://www.zty.org/index.php
.....
Concurrency Level: 10
Time taken for tests: 0.396 seconds
Complete requests: 5000
Failed requests: 0
.....
七、Nginx 二次开发版本
7.1 openresty
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服 务和动态网关。
OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
OpenResty 由于有功能强大且方便的的API,可扩展性更强,如果需要实现定制功能,OpenResty是个不错的选择
官网: http://openresty.org/cn/
7.2 编译安装 openresty
[root@Nginx-node1 ~]# dnf -yq install gcc pcre-devel openssl-devel perl
[root@Nginx-node1 ~]# useradd -r -s /sbin/nologin nginx
[root@Nginx-node1 ~]# wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@nginx-node1 ~]# tar zxf openresty-1.25.3.1.tar.gz
[root@nginx-node1 ~]# cd openresty-1.25.3.1/
[root@nginx-node1 openresty-1.25.3.1]# ./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-node1 openresty-1.25.3.1]# gmake -l4 && gmake install
[root@nginx-node1 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/openresty/bin
[root@nginx-node1 ~]# source ~/.bash_profile
[root@nginx-node1 ~]# openresty -v
nginx version: openresty/1.25.3.1
[root@nginx-node1 ~]# openresty
[root@nginx-node1 ~]# ps aux | grep nginx
root 11598 0.0 0.0 13048 1712 ? Ss 20:28 0:00 nginx: master process openresty
nginx 11599 0.0 0.3 15916 5332 ? S 20:28 0:00 nginx: worker process
root 11603 0.0 0.1 221680 2364 pts/0 S+ 20:28 0:00 grep --color=auto nginx
主配置文件路径:/usr/local/openresty/nginx/conf/nginx.conf 与nginx一样
上述所有对于nginx的操作在openresty都能适用