一.Web 服务基础介绍
1.1 互联网发展历程
1993年3月2日,中国科学院高能物理研究所租用AT&T公司的国际卫星信道建立的接入美国SLAC国家实 验室的64K专线正式开通,成为我国连入Internet的第一根专线。
1995年马云开始创业并推出了一个web网站 中国黄页
1999年创建阿里巴巴 www.alibabagroup.com
2003年5月10日创立淘宝网
2004年12月,马云创立第三方网上支付平台支付宝(蚂蚁金服旗下,共有蚂蚁金服支付宝、余额宝、招 财宝、蚂蚁聚宝、网商银行、蚂蚁花呗、芝麻信用等子业务板块)
1.2 Web 服务介绍
Apache prefork 模型
预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
每个子进程有一个独立的线程响应用户请求
相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
Apache worker 模型
- 一种多进程和多线程混合的模型
- 有一个控制进程,启动多个子进程
- 每个子进程里面包含固定的线程
- 使用线程程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,
- 由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在prefork模式下,同样会发生)
Apache event模型
- Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)
- 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
- 它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题
- (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
- event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
- 当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
1.2.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 ),2019年3月11日 F5 Networks 6.7亿美元的价格收购,Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器解决C10K问题(10K Connections)
Nginx官网: nginx news
nginx的其它的二次发行版:
-
Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加 了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了 很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始, Tengine成为一个开源项目官网: The Tengine Web Server
-
OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发,官网: esty.org/cn/
2.1.2 Nginx 功能介绍
-
静态的web资源服务器html,图片,js,css,txt等静态资源
-
http/https协议的反向代理
-
结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
-
tcp/udp协议的请求转发(反向代理)
-
imap4/pop3协议的反向代理
2.2.3 基础特性
-
模块化设计,较好的扩展性
-
高可靠性
-
支持热部署:不停机更新配置文件,升级版本,更换日志文件
-
低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
-
event-driven,aio,mmap,sendfile
2.2.4 Web 服务相关的功能
-
虚拟主机(server)
-
支持 keep-alive 和管道连接(利用一个连接做多次请求)
-
访问日志(支持基于日志缓冲提高其性能) http://openr
-
url rewirte
-
路径别名
-
基于IP及用户的访问控制
-
支持速率限制及并发数限制
-
重新配置和在线升级而无须中断客户的工作进程
2.2 Nginx 架构和进程
2.2.2 Nginx 进程结构
web请求处理机制
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直 到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务 器资源耗尽而无法提供请求
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客 户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器 对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可 以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作 了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组
主进程(master process)的功能:
对外接口:接收外部的操作(信号)
对内转发:根据外部的操作的不同,通过信号管理 Worker 监控:
监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程
读取Nginx 配置文件并验证其有效性和正确性
建立、绑定和关闭socket连接
按照配置生成、管理和结束工作进程
接受外界指令,比如重启、升级及退出服务器等指令
不中断服务,实现平滑升级,重启服务并应用新的配置
开启日志文件,获取文件描述符
不中断服务,实现平滑升级,升级失败进行回滚处理
编译和处理perl脚本
工作进程(worker process)的功能:
所有 Worker 进程都是平等的
实际处理:网络请求,由 Worker 进程处理
Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争 CPU资源,
增加上下文切换的损耗
接受处理客户的请求
将请求依次送入各个功能模块进行处理
I/O调用,获取响应数据
与后端服务器通信,接收后端服务器的处理结果
缓存数据,访问缓存索引,查询和调用缓存数据
发送请求结果,响应客户的请求
接收主程序指令,比如重启、升级和退出等
2.2.4 Nginx 启动和 HTTP 连接建立
Nginx 启动时,Master 进程,加载配置文件
Master 进程,初始化监听的 socket
Master 进程,fork 出多个
Worker 进程 Worker 进程,竞争新的连接,获胜方通过三次握手,建立 Socket 连接,并处理请求
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
[root@nginx-node ~]# wget https://nginx.org/download/nginx-1.26.2.tar.gz
[root@nginx-node ~]# wget https://nginx.org/download/nginx-1.24.
[root@nginx-node ~]# tar zxf nginx-1.24.0.tar.gz
[root@nginx-node ~]# tar zxf nginx-1.26.2.tar.gz
[root@nginx-node ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@nginx-node ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@nginx-node ~]# ls
公共 下载 echo-nginx-module-0.63.tar.gz nginx-1.26.2
模板 音乐 memc-nginx-module-0.20 nginx-1.26.2.tar.gz
视频 桌面 memc-nginx-module-0.20.tar.gz srcache-nginx-module-0.33
图片 anaconda-ks.cfg nginx-1.24.0 srcache-nginx-module-0.33.
文档 echo-nginx-module-0.63 nginx-1.24.0.tar.gz
[root@nginx-node ~]# cd nginx-1.2
[root@nginx-node nginx-1.26.2]# ./configure --help| less
[root@nginx-node nginx-1.26.2]# dnf install gcc -y
[root@nginx-node nginx-1.26.2]# useradd -s /sbin/nologin -M nginx
[root@nginx-node nginx-1.26.2]# ./configure --prefix=/usr/local/nginx --add-module=/root/echo-nginx-module-0.63 --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33 --user=nginx --group=nginx --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-pcre
[root@Nginx nginx-1.26.0]# make && make install
nginx完成安装以后,有四个主要的目录
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin
src
README
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 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx-node nginx-1.26.2]# source ~/.bash_profile
2.4.2.3使用安装完成的二进制文件nginx
2.4.2.4Ngnix启动文件
范例
[root@nginx-node1 ~]# nginx
[root@nginx-node1 ~]# cd /usr/local/nginx/logs/
[root@nginx-node1 logs]# ls
access.log error.log nginx.pid
[root@nginx-node1 sbin]# 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
~
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 平滑升级和回滚案例
[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.24.0.tar.gz
[root@nginx-node1 ~]# tar zxf nginx-1.24.0.tar.gz
[root@nginx-node1 nginx-1.24.0]# dnf install gcc -y
#开始编译新版本
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
# 错误
[root@nginx-node1 nginx-1.24.0]# dnf search pcre
[root@nginx-node1 nginx-1.24.0]# dnf install pcre-devel.x86_64 -y
# 检测
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx-node1 nginx-1.24.0]# dnf search OpenSSL
[root@nginx-node1 nginx-1.24.0]# dnf install openssl-devel.x86_64
#检测
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx-node1 nginx-1.24.0]# dnf install zlib-devel.x86_64
# 检测
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
# 成功,生成makefile文件
[root@nginx-node1 nginx-1.24.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
# 清空,重新检测
[root@nginx-node1 nginx-1.24.0]# make clean
rm -rf Makefile objs
[root@nginx-node1 nginx-1.24.0]# ls
auto CHANGES.ru configure html man src
CHANGES conf contrib LICENSE README
# 检测
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx-node1 nginx-1.24.0]# ls
auto CHANGES.ru configure html man src
CHANGES conf contrib LICENSE README
[root@nginx-node1 nginx-1.24.0]# make -j2
[root@nginx-node1 nginx-1.24.0]# make install
[root@nginx-node1 local]# cd /usr/local/nginx/
[root@nginx-node1 nginx]# ls
conf html logs sbin
[root@nginx-node1 nginx]# cd sbin/
[root@nginx-node1 sbin]# ls
nginx
[root@nginx-node1 sbin]# useradd -s /sbin/nologin -M nginx
[root@nginx-node1 sbin]# id nginx
用户id=1001(nginx) 组id=1001(nginx) 组=1001(nginx)
[root@nginx-node1 sbin]# ./nginx
[root@nginx-node1 sbin]# ps aux | grep nginx
root 50715 0.0 0.0 9832 936 ? Ss 13:17 0:00 nginx: master process ./nginx
nobody 50716 0.0 0.1 13720 4640 ? S 13:17 0:00 nginx: worker process
root 50722 0.0 0.0 221680 2388 pts/2 S+ 13:17 0:00 grep --color=auto nginx
# 80端口
[root@nginx-node1 sbin]# ps aux | grep nginx
root 50715 0.0 0.0 9832 936 ? Ss 13:17 0:00 nginx: master process ./nginx
nobody 50716 0.0 0.1 13720 4640 ? S 13:17 0:00 nginx: worker process
root 50722 0.0 0.0 221680 2388 pts/2 S+ 13:17 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# netstat -antlupe | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 84003 50715/nginx: master
[root@nginx-node1 ~]# /usr/local/nginx/sbin/nginx -s stop
# 关闭nginx
# 没有端口号
[root@nginx-node1 ~]# netstat -antlupe | grep nginx
[root@nginx-node1 nginx-1.24.0]# rm -fr /usr/local/nginx/
[root@nginx-node1 nginx-1.24.0]# make clean
rm -rf Makefile objs
# 关闭debug功能
[root@nginx-node1 nginx-1.24.0]# vim auto/cc/gcc
访问成功
平滑升级
[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.26.2.tar.gz
[root@nginx-node1 ~]# ls
公共 视频 文档 音乐 anaconda-ks.cfg nginx-1.24.0 nginx-1.26.2.tar.gz
模板 图片 下载 桌面 echo-nginx-module-0.63.tar.gz nginx-1.24.0.tar.gz
[root@nginx-node1 ~]# tar zxf echo-nginx-module-0.63.tar.gz
[root@nginx-node1 ~]# tar zxf nginx-1.26.2.tar.gz
[root@nginx-node1 core]# vim nginx.h
[root@nginx-node1 core]# pwd
/root/nginx-1.24.0/src/core
修改前
修改后
[root@nginx-node1 nginx-1.26.2]# ./configure --prefix=/usr/local/nginx --group=nginx --add-module=/root/echo-nginx-module-0.63 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx-node1 nginx-1.26.2]# make
# 编译后生成目录的文件位置
[root@nginx-node1 nginx-1.26.2]# cd objs/
[root@nginx-node1 objs]# ls
addon Makefile nginx.8 ngx_auto_headers.h ngx_modules.o
autoconf.err nginx ngx_auto_config.h ngx_modules.c src
[root@nginx-node1 nginx-1.24.0]# cd /usr/local/nginx/
[root@nginx-node1 nginx]# ls
conf html logs sbin
[root@nginx-node1 nginx]# cd sbin/
[root@nginx-node1 sbin]# ls
nginx
[root@nginx-node1 sbin]# nginx
[root@nginx-node1 sbin]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: timinglee/1.0
Date: Thu, 15 Aug 2024 06:13:07 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 06:11:48 GMT
Connection: keep-alive
ETag: "66bd9c24-267"
Accept-Ranges: bytes
#把之前的旧版的nginx命令备份
[root@nginx-node1 sbin]# cp nginx nginx.old
#把新版本的nginx命令复制过去
[root@nginx-node1 sbin]# \cp -f /root/nginx-1.26.2/objs/nginx /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ll
总用量 7220
-rwxr-xr-x 1 root root 6151032 8月 15 14:14 nginx
-rwxr-xr-x 1 root root 1237312 8月 15 14:13 nginx.old
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 936 ? Ss 14:13 0:00 nginx: master processnginx
nobody 60359 0.0 0.1 13720 4640 ? S 14:13 0:00 nginx: worker process
root 60397 0.0 0.0 221680 2312 pts/1 S+ 14:15 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# pidof nginx
60359 60358
[root@nginx-node1 sbin]# kill -USR2 60358 #nginx worker ID
#USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的
nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 2612 ? Ss 14:13 0:00 nginx: master processnginx
nobody 60359 0.0 0.1 13720 4640 ? S 14:13 0:00 nginx: worker process
root 60402 0.0 0.1 9860 6064 ? S 14:16 0:00 nginx: master processnginx
nobody 60403 0.0 0.1 13748 4592 ? S 14:16 0:00 nginx: worker process
root 60407 0.0 0.0 221680 2372 pts/1 S+ 14:16 0:00 grep --color=auto nginx
回收旧版本
[root@nginx-node1 sbin]# kill -WINCH 60358
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 2612 ? Ss 14:13 0:00 nginx: master process nginx
root 60402 0.0 0.1 9860 6064 ? S 14:16 0:00 nginx: master process nginx
nobody 60403 0.0 0.1 13748 4592 ? S 14:16 0:00 nginx: worker process
root 60410 0.0 0.0 221680 2300 pts/1 S+ 14:19 0:00 grep --color=auto nginx
# 完成升级
[root@nginx-node1 sbin]# curl -I 172.25.254.100
回滚
[root@nginx-node1 sbin]# kill -HUP 60358
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 2612 ? Ss 14:13 0:00 nginx: master process nginx
root 60402 0.0 0.1 9860 6064 ? S 14:16 0:00 nginx: master process nginx
nobody 60403 0.0 0.1 13748 4592 ? S 14:16 0:00 nginx: worker process
nobody 60412 0.0 0.1 13720 4640 ? S 14:21 0:00 nginx: worker process
root 60414 0.0 0.0 221680 2316 pts/1 S+ 14:21 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -WINCH 60402
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 2612 ? Ss 14:13 0:00 nginx: master process nginx
root 60402 0.0 0.1 9860 6064 ? S 14:16 0:00 nginx: master process nginx
nobody 60412 0.0 0.1 13720 4640 ? S 14:21 0:00 nginx: worker process
root 60418 0.0 0.0 221680 2444 pts/1 S+ 14:24 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# curl -I 172.25.254.100
[root@nginx-node1 sbin]# cp nginx nginx.new
[root@nginx-node1 sbin]# \cp -f nginx.old nginx
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60358 0.0 0.0 9832 2612 ? Ss 14:13 0:00 nginx: master process nginx
root 60402 0.0 0.1 9860 6064 ? S 14:16 0:00 nginx: master process nginx
nobody 60412 0.0 0.1 13720 4640 ? S 14:21 0:00 nginx: worker process
root 60440 0.0 0.0 221680 2436 pts/1 S+ 14:27 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -9 60402
三.Nginx 核心配置详解
3.1 配置文件说明
-
主配置文件:nginx.conf
-
子配置文件: include conf.d/*.conf
-
fastcgi, uwsgi,scgi 等协议相关的配置文件
-
mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮 件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某 种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动 使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
默认的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 (快速拷贝到kernelsocket
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
#这个跟对应其server中定义的目录下。
root html; #定义默认页面所在的目录
}
}
#和邮件相关的配置
#mail {
# ...
# } mail 协议相关配置段
#tcp代理配置,1.9版本以上支持
#stream {
# ...
# } stream 服务器相关配置段
#导入其他路径的配置文件
#include /apps/nginx/conf.d/*.conf
}
3.2 全局配置
Main 全局配置段常见的配置指令分类
-
正常运行必备的配置
-
优化性能相关的配置
-
用于调试及定位问题相关的配置
-
事件驱动相关的配置
范例:
实现 nginx 的高并发配置
[root@nginx-node1 sbin]# systemctl daemon-reload
[root@nginx-node1 sbin]# nginx -s stop
[root@nginx-node1 sbin]# pa aux | grep nginx
bash: pa: command not found...
[root@nginx-node1 sbin]# ps aux | grep nginx
root 60935 0.0 0.0 221680 2412 pts/1 S+ 16:33 0:00 grep --color=auto nginx
[root@nginx-node1 ~]# systemctl enable --now nginx
[root@nginx-node1 ~]# ps aux | grep nginx
root 60976 0.0 0.0 9860 944 ? Ss 21:14 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 60977 0.0 0.1 13760 4684 ? S 21:14 0:00 nginx: worker process
root 61323 0.0 0.0 221680 2388 pts/0 S+ 22:13 0:00 grep --color=auto nginx
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# ps aux | grep nginx
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# ps aux | grep nginx
实现nginx的高并发配置
# 安装压力测试软件
[root@nginx-node1 ~]# dnf install httpd-tools -y
#
[root@nginx-node1 ~]# ab -n 1000 -c 500 http://172.25.254.100/index.html
[root@nginx-node1 ~]# ab -n 10000 -c 5000 http://172.25.254.100/index.html
# 修改pam限制
[root@nginx-node1 ~]# vim /etc/security/limits.conf
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
3.3 核心配置示例
基于不同的IP、不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块 ngx_http_core_module实现。
3.3.1 新建一个 PC web 站点
#定义子配置文件路径
[root@Nginx ~]# mkdir /usr/local/nginx/conf.d/
[root@centos8 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
......
include /apps/nginx/conf/conf.d/*.conf;
生效
}
#创建虚拟主机网站配置
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name lee.timinglee.org;
location / {
root /webdata/nginx/timinglee.org/lee/html;
}
}
#在配置文件的最后面添加此行
#注意不要放在最前面,会导致前面的命令无法
[root@Nginx ~]# mkdir -p /webdata/nginx/timinglee.org/lee/html
[root@Nginx ~]# echo lee.timinglee.org >
/webdata/nginx/timinglee.org/lee/html/index.html
[root@Nginx ~]# nginx -s reload
#访问测试
[root@node100 ~]# curl lee.timinglee.org
lee.timinglee.org
3.3.2 root 与 alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location root示例:root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location
示例:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
}
[root@nginx-node1 ~]# mkdir -p /data/web/html
[root@nginx-node1 ~]# echo www.timinglee.org > /data/web/html/index.html
[root@nginx-node1 ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx-node1 ~]# nginx -s reload
Windows作解析
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于 location上下文,此指令使用较少
alias示例:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@nginx-node1 ~]# mkdir /data/web/test1 -p
[root@nginx-node1 ~]# echo /data/web/test1 > /data/web/test1/index.html
[root@nginx-node1 ~]# nginx -t
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
3.3.3 location 的详细使用
-
在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;
-
ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,
-
而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最 高的一个uri
-
uri是用户请求的字符串,即域名后面的web文件路径
-
然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理 此请求
匹配案例
精确匹配
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# mkdir /data/web/test -p
[root@nginx-node1 ~]# echo test page > /data/web/test/index.html
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# mkdir /data/web{1,2}
[root@nginx-node1 ~]# mkdir /data/web{1,2}/test
[root@nginx-node1 ~]# echo web1 test > /data/web1/test/index.html
[root@nginx-node1 ~]# echo web2 test > /data/web2/test/index.html
[root@nginx-node1 ~]# nginx -s reload
文件名后缀
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# mkdir -p /data/web1/{test1,tee}
[root@nginx-node1 ~]# echo test1 > /data/web1/test1/index.html
[root@nginx-node1 ~]# echo tee > /data/web1/tee/index.html
[root@nginx-node1 ~]# mkdir -p /data/web1/lee/index.html
[root@nginx-node1 ~]# nginx -s reload
优先级
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# mkdir -p /data/web{1..5}
[root@nginx-node1 ~]# mkdir -p /data/web{1..5}/test
[root@nginx-node1 ~]# echo web1 > /data/web1/test/index.html
[root@nginx-node1 ~]# echo web2 > /data/web2/test/index.html
[root@nginx-node1 ~]# echo web3 > /data/web3/test/index.html
[root@nginx-node1 ~]# echo web4 > /data/web4/test/index.html
[root@nginx-node1 ~]# echo web5 > /data/web5/test/index.html
web4和web5 优先级一样,那个在前面先匹配那个
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
依次类推,比较优先级
3.3.4 Nginx 账户认证功能
由 ngx_http_auth_basic_module 模块提供此功能
示例:
[root@nginx-node1 ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx-node1 ~]# htpasswd -m /usr/local/nginx/.htpasswd Gao
New password:
Re-type new password:
Adding password for user Gao
[root@nginx-node1 ~]# mkdir /data/web/Gao
[root@nginx-node1 ~]# echo Gao > /data/web/Gao/index.html
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
# location = /test {
# root /data/web2;
# }
# location /test {
# root /data/web1;
# }
# location ^~ /t {
# root /data/web3;
# }
# location ~ .(html)$ {
# root /data/web4;
# }
# location ~* .HTML$ {
# root /data/web5;
# }
location /Gao {
root /data/web;
auth_basic "login password !!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
}
3.3.5 自定义错误页面
自 定义错误页,同时也可以用指定的响应状态码进行响应, 可用位置:http, server, location, if in location
示例:
listen 80;
server_name www.timinglee.org;
error_page 500 502 503 504 /error.html;
location = /error.html {
root /data/nginx/html;
}
#重启nginx并访问不存在的页面进行测试
[root@nginx-node1 ~]# mkdir -p /data/web/errorpage
[root@nginx-node1 ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
3.3.6 错误日志
# 自定义日志
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
error_log /var/log/timinglee.org/error.log;
access_log /var/log/timinglee.org/access_log;
location /Gao {
root /data/web;
auth_basic "login password !!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location /40x.html {
root /data/web/errorpage;
}
}
3.3.7 检测文件是否存在
try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如 果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一 个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内 部500错误。
示例: 如果不存在页面, 就转到default.html页面
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.timinglee.org
www.timinglee.org
[root@nginx-node1 ~]# rm -fr /data/web/html/index.html
[root@nginx-node1 ~]# rm -fr /data/web/html/error
[root@nginx-node1 ~]# curl www.timinglee.org
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx/1.26.2</center>
</body>
</html>
[root@nginx-node1 ~]# mkdir /data/web/html/error
[root@nginx-node1 ~]# cat /data/web/html/error/index.html
error default
[root@nginx-node1 ~]# echo error default > /data/web/html/error/default.html
[root@nginx-node1 ~]# curl www.timinglee.org
error default
3.3.8 长连接配置
范例:
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
# 安装测试工具
[root@nginx-node1 ~]# dnf install telent -y
正在更新 Subscription Management 软件仓库。
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
keepalive_timeout 65; # 长连接等待时间/
keepalive_requests 2;
# 长连接请求次数为2
[root@nginx-node1 ~]# echo www.timinglee.org > /data/web/html/index.htmlnmc
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# telnet www.timinglee.org 80
# 连接俩次自动断开
3.3.9 作为下载服务器配置
ngx_http_autoindex_module 模块处理以斜杠字符 "/" 结尾的请求,并生成目录列表,可以做为下载服务
示例:实现下载站点
[root@nginx-node1 ~]# mkdir /data/web/download
[root@nginx-node1 ~]# dd if=/dev/zero of=/data/web/download/leefile bs=1M count=100
记录了100+0 的读入
记录了100+0 的写出
104857600字节(105 MB,100 MiB)已复制,0.0235591 s,4.5 GB/s
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx-node1 ~]# nginx -s reload
限速功能
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
四.Nginx 高级配置
4.1 Nginx 状态页
-
基于nginx 模块 ngx_http_stub_status_module 实现,
-
在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
-
否则配置完成之后监测会是提示法错误
注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态
范例
windows.虚拟机做本地解析
C:\Windows\System32\drivers\etc\hosts
[root@nginx-node1 ~]# vim /etc/hosts
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/status.conf
server {
listen 80;
server_name status.timinglee.org;
root /data/web/html;
index index.html;
location /status {
stub_status;
allow 172.25.254.1;
deny all;
}
}
[root@nginx-node1 conf.d]# nginx -s reload
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
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_http_version 1.1;
gzip_vary on;
gzip_types text/plain application/javascript application/x-javascript text/css
application/xml text/javascript application/x-httpd-php image/gif image/png;
[root@nginx-node1 ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf synta x is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is s uccessful
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# echo hello GXY > /data/web/html/small.html
[root@nginx-node1 ~]# du -sh /usr/local/nginx/logs/access.log
120K /usr/local/nginx/logs/access.log
[root@nginx-node1 ~]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html
3.4 Nginx 变量使用
-
nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
-
变量可以分为内置变量和自定义变量
-
内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
3.4.1 内置变量
常用内置变量
$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名
#示例:
echo $http_user_agent;
echo $http_host;
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有
横线需要替换为下划线
$sent_http_<name>
#name为响应报文的首部字段,name的对应的首部字段名需要为小写,如果有横线需要替换为下划线,此变量有
问题
echo $sent_http_server;
$arg_<name>
#此变量存放了URL中的指定参数,name为请求url中指定的参数
echo $arg_id;
范例:
# 内置变量
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
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 conf.d]# cd /usr/local/nginx/conf.d/
[root@nginx-node1 conf.d]# nginx -s reload
[root@nginx-node1 conf.d]# curl -b "key1=lee,key2=lee1" -u lee:lee var.timinglee.org/var?name=lee&&id=6666
172.25.254.100
name=lee
?
/data/web/html
/var
var.timinglee.org
35084
lee
GET
/data/web/html/var
/var?name=lee
http
HTTP/1.1
172.25.254.100
var.timinglee.org
80
curl/7.76.1
key1=lee,key2=lee1
lee1
3.2.2自定义变量
范例:
server {
listen 80;
server_name var1.timinglee.org;
root /data/web/html;
index index.html;
location /var {
default_type text/html;
set $timinglee lee;
echo $timinglee;
}
}
# 测试输出
[root@nginx-node1 conf.d]# nginx -s reload
[root@nginx-node1 conf.d]# curl -b "key1=lee,key2=lee1" -u lee:lee var1.timinglee.o/var?name=lee&&id=6666
lee
五 Nginx Rewrite 相关功能
-
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
-
此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
-
rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
-
比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的 链接,就可以设置为访问
-
另外还可以在一定程度上提高网站的安全性。
5.1ngx_http_rewrite_module 模块指令
官方文档 : https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
if 指令
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断,用法如下:
if (条件匹配) {
action
}
[root@nginx-node1 conf.d]# vim vars.conf
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location /test {
if ( !-e $request_filename ){
echo "$request_filename is exist";
}
}
}
5.1.1set指令
[root@nginx-node1 conf.d]# cat var1.conf
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location /var {
default_type text/html;
set $haha hello; #变量可以随便起名字
echo $haha;
}
}
5.1.2break 指令
- 用于中断当前相同作用域(location)中的其他Nginx配置
- 与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
- 位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
- Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置
- 该指令可以在server块和locationif块中使用
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location /break {
default_type text/html;
set $name haha;
echo $name;
break;
set $id 666;
echo $id;
}
[root@nginx-node1 conf.d]# curl var.haha.org/break
haha
5.1.3return 指令
return 用于完成对请求的处理,并直接向客户端返回响应状态码,比如 : 可以指定重定向 URL( 对于特殊重定向状态码,301/302 等 ) 或者是指定提示文本内容 ( 对于特殊状态码 403/500 等 ) ,处于此指令后的所有配置都将不被执行,return 可以在 server 、 if 和 location 块进行配置
格式:
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容
#可以调用变量,其中text如果有空格,需要用单或双引号
return code URL; #返回给客户端的URL地址
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location /return {
default_type text/html;
if ( !-e $request_filename){
return 301 http://www.baidu.com;
}
echo "$request_filename is exist";
}
当我们访问/return时,如果文件不存在,就返回一个301并且重定向到百度去。如果存在就输出存在。
测试:
[root@nginx-node1 conf.d]# mkdir /data/web/html/return
[root@nginx-node1 conf.d]# nginx -s reload
[root@nginx-node1 conf.d]# curl -I var.haha.org/return
HTTP/1.1 200 OK
Server: lf/1.0
Date: Sun, 18 Aug 2024 11:50:00 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
5.2rewrite 指令
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理
官方文档: Module ngx_http_rewrite_module
语法格式 :
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.1rewrite 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
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作
#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,
#而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
5.2.2域名永久与临时重定向
域名的临时的调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳转,这种情况浏览器不会缓存跳转,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。
将访问源域名 var .haha.org 的请求永久重定向到 www.haha.com
5.2.2.1 永久重定向301
[root@nginx-node1 conf.d]# cat vars.conf
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
rewrite / http://www.haha.com permanent;
# rewrite / http://www.haha.com redirect;
}
}
5.2.2.2 临时重定向302
域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器 不会缓存当前域名的解析记录,而浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久 重定向最大的本质区别。 即当nginx服务器无法访问时,浏览器不能利用缓存,而导致重定向失败
[root@nginx-node1 conf.d]# cat vars.conf
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
# rewrite / http://www.haha.com permanent;
rewrite / http://www.haha.com redirect;
}
}
测试
[root@nginx-node1 conf.d]# curl -I var.haha.org
HTTP/1.1 302 Moved Temporarily
Server: lf/1.0
Date: Sun, 18 Aug 2024 12:38:26 GMT
Content-Type: text/html
Content-Length: 139
Connection: keep-alive
Location: http://www.haha.com
5.2.3 rewrite 案例: break 与 last
测试: 访问break请求被rewrite至test1,而访问test1转递请求再次被rewrite发送至test2,此测试last和break 分别有什么区别
[root@nginx-node conf.d]# mkdir /data/web/html/{a1,a2,break,last}
[root@nginx-node conf.d]# echo test1 > /data/web/html/a1/index.html
[root@nginx-node conf.d]# echo test2 > /data/web/html/a2/index.html
[root@nginx-node conf.d]# echo break > /data/web/html/break/index.html
[root@nginx-node conf.d]# echo last > /data/web/html/last/index.html
[root@nginx-node conf.d]# cat vars.conf
server {
listen 80;
server_name var.haha.org;
root /data/web/html;
index index.html;
location /break {
rewrite ^/break/(.*) /a1/$1;
rewrite ^/a1/(.*) /a2/$1;
}
location /last {
rewrite ^/last/(.*) /a1/$1;
rewrite ^/a1/(.*) /a2/$1;
}
location /a1 {
default_type text/html;
echo "hahahaha";
}
location /a2 {
root /data/web/html;
}
}
[root@nginx-node1 conf.d]# curl var.haha.org/break/
test2
[root@nginx-node1 conf.d]# curl var.haha.org/last/
test2
使用break
[root@nginx-node1 conf.d]# curl var.haha.org/break/index.html
test1
使用last
[root@nginx-node1 conf.d]# curl var.haha.org/last/index.html
hahahahaha
5.2.4 rewrite案例: 自动跳转 https
范例:基于通信安全考虑公司网站要求全站 https,因此要求将在不影响用户请求的情况下将http请求全 部自动跳转至 https,另外也可以实现部分 location 跳转
[root@nginx-node1 nginx]# mkdir certs
[root@nginx-node1 nginx]# cd certs/
[root@nginx-node1 certs]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/haha.org.key -x509 -days 365 -out /usr/local/nginx/certs/haha.org.key.crt
....+......+.........+...........+...+...+..........+........+.......+.....+....+........+...+..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+...+.....+...+..........+.....+.........+.+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+......+.+..+.......+......+.....+..........+..+...............+.+.....+.+...........+.............+......+.........+.....+.........+...+...+....+..+......+...+.......+..+.......+...+............+...+...+..+...+..................+.+.....+.+..+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+......+...+..+....+.....+............+...+......+.....................+....+........+......+....+..+.+........+......+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
[root@nginx-node1 certs]# ls
haha.org.key haha.org.key.crt
server {
listen 80;
listen 443 ssl;
server_name var.haha.org;
root /data/web/html;
index index.html;
ssl_certificate_key /usr/local/nginx/certs/haha.org.key;
ssl_certificate /usr/local/nginx/certs/haha.org.crt;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
}
测试
[root@nginx-node1 conf.d]# cat /data/web/html/index.html
haha
[root@nginx-node1 conf.d]# vim vars.conf
[root@nginx-node1 conf.d]# curl var.haha.org
haha
使用rewrite指令临时重定向,跳转https
listen 80;
listen 443 ssl;
server_name var.haha.org;
root /data/web/html;
index index.html;
ssl_certificate_key /usr/local/nginx/certs/haha.org.key;
ssl_certificate /usr/local/nginx/certs/haha.org.crt;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
if ( $scheme = http ){
rewrite /(.*) https://$HOST/$1 redirect;
}
}
location /login {
if ( $scheme = http ){
rewrite /login https://$HOST/login redirect;
}
}
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
六 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,
参数
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
#重启Nginx测试访问效果:
#curl -L http://www.timinglee.org/web
#如果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范例
反代理单台 web 服务器
node1 | 172.25.254.100 | ngnix反向代理 |
---|---|---|
web10 | 172.25.254.10 | real server1 |
web20 | 172.25.254.20 | real server2 |
俩台real server安装apache,实现web服务
[root@web10 ~]# yum install httpd
[root@web10 ~]# systemctl enable --now httpd
[root@web10 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@web20 ~]# yum install httpd
[root@web20 ~]# systemctl enable --now httpd
[root@web20 ~]# echo 172.25.254.10 > /var/www/html/index.html
[root@nginx-node ~]# curl 172.25.254.10
172.25.254.10
[root@nginx-node ~]# curl 172.25.254.20
172.25.254.20
# 在nginx构建反向代理
server {
listen 80;
server_name www.haha.org;
location / {
proxy_pass http://172.25.254.10:80;
}
}
~
指定 location 实现反向代理
在node2上新建一个目录
[root@web20 ~]# mkdir /var//www/html/static
[root@web20 ~]# echo web20 - 172.25.254.20 > /var/www/html/static/index.html
vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
server_name www.haha.org;
location / {
proxy_pass http://172.25.254.10:80;
}
location /static {
proxy_pass http://172.25.254.20:80;
}
指定 location 实现动静分离反向代理
在node上安装php,实现动态资源,node1依然使用html,实现静态资源
[root@web10 ~]# cat /var/www/html/index.php
<?php
phpinfo();
?>
[root@web10 ~]# systemctl restart httpd.service
[root@nginx-node ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
server_name www.haha.org;
location ~ \.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static{
proxy_pass http://172.25.254.20:80;
}
访问nginx服务器测试
反向代理:缓存功能
缓存功能默认关闭状态,需要先动配置才能启用
proxy_cache zone_name | off; 默认off
#指明调用的缓存,或关闭缓存机制;Context:http, server, location
#zone_name 表示缓存的名称.需要由proxy_cache_path事先定义
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@nginx-node ~]# ab -n1000 -c100 http://www.haha.org/static/index.html
准备缓存配置
在主配置文件内添加参数
在子配置文件loaction中添加
[root@nginx-node ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
server_name www.haha.org;
location ~ \.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static{
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; #缓存其他的响应时间
}
配置完成后,刷新配置,缓存目录会自动生成‘
[root@nginx-node ~]# ll -d /usr/local/nginx/proxy_cache/ -d
drwx------. 2 nginx root 6 8月 20 12:46 /usr/local/nginx/proxy_cache/
[root@nginx ~]# cd /usr/local/nginx/proxy_cache/
[root@nginx proxy_cache]# ll
总用量 0
访问并验证缓存文件
[root@nginx-node proxy_cache]# ab -n1000 -c100 http://www.haha.org/static/index.html
6.1.2 http 反向代理负载均衡
在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而 且不能对后端服务器提供相应的服务器状态监测,Nginx 可以基于ngx_http_upstream_module模块提 供服务器分组转发、权重分配、状态监测、调度算法等高级功能
官方文档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
反向代理后端多台 web服务器
编写nginx子配置文件
upstream webcluster {
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.haha.org;
location / {
proxy_pass http://webcluster;
}
}
基于uri进行hash
upstream webcluster {
hash $request_uri consistent;
server 172.25.254.10:8080 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.haha.org;
location / {
proxy_pass http://webcluster;
}
}
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
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.1 负载均衡实例: MySQL
后端服务器安装 MySQL
[root@web10 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@web10 ~]# mysql -e "grant all on *.* to haha@'%' identified by 'haha';"
[root@web10 ~]# mysql -uhaha -p123 -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
[root@web20 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@web20 ~]# systemctl start mariadb.service
[root@web20 ~]# mysql -e "grant all on *.* to haha@'%' identified by 'haha';"
# 启动服务
# 设置mysql可远程登陆的账户和密码
[root@nweb20 ~]# mysql -uhaha -p123 -h172.25.254.20 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 10 |
+-------------+
配置nginx服务器
[root@nginx-node ~]# vim /usr/local/nginx/conf.d/vars.conf
stream {
upstream mysql_server {
server 172.25.254.10:3306 fail_timeout=15s max_fails=3;
server 172.25.254.20:3306 fail_timeout=15s max_fails=3;
}
server {
listen 172.25.254.100:3306;
proxy_pass mysql_server;
proxy_connect_timeout 30s;
proxy_timeout 300s;
}
}
[root@nginx-node ~]# mkdir /usr/local/nginx/tcpconf.d
[root@nginx-node ~]# mv /usr/local/nginx/conf.d/vars.conf /usr/local/nginx/tcpconf.d/
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处 理,其配置指令如下:
#转发请求到后端服务器,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实战案例
编译安装更方便自定义参数或选项,所以推荐大家使用源码编译
官方网站: www.php.net
源码编译 php
#利用yum解决php依赖
[root@Nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel
libpng-devel libcurl-devel oniguruma-devel
#解压源码并安装
[root@Nginx ~]# ./configure \
--prefix=/usr/local/php \ #安装路径
--with-config-file-path=/usr/local/php/etc \ #指定配置路径
--enable-fpm \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cg
解压缩php的安装包
[root@nginx ~]# tar xvf php-8.3.9.tar.gz
# 安装
[root@nginx-node 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@nginx-node 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@nginx-node php-8.3.9]# dnf install systemd-devel -y
[root@nginx-node php-8.3.9]# dnf whatprovides */libxml-2.0*
[root@nginx-node php-8.3.9]# dnf install libxml2-devel-2.9.13-2.el9.x86_64
[root@nginx-node 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@nginx-node php-8.3.9]# dnf search sqlite3
[root@nginx-node php-8.3.9]# dnf install sqlite-devel.x86_64
[root@nginx-node 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@nginx-node php-8.3.9]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel
[root@nginx-node ~]# cd /mnt/
[root@nginx-node mnt]# wget https://mirrors.aliyun.com/rockylinux/9.4/devel/x86_64/os/Packages/o/oniguruma-devel-6.9.6-1.el9.5.0.1.x86_64.rpm
[root@nginx-node ~]# dnf install 'oniguruma-devel-6.9.6-1.el9.5.x86_64 (2).rpm'
[root@nginx-node 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@nginx-node php-8.3.9]# make && make install
php相关配置优化
[root@Nginx ~]# cd /usr/local/php/etc
[root@Nginx etc]# cp php-fpm.conf.default php-fpm.conf
[root@Nginx etc]# vim php-fpm.conf
去掉注释
pid = run/php-fpm.pid
#指定pid文件存放位置
[root@nginx-node etc]# ls
php-fpm.conf php-fpm.conf.default php-fpm.d
[root@nginx-node etc]# cd php-fpm.d/
[root@nginx-node php-fpm.d]# ls
www.conf.default
[root@nginx-node php-fpm.d]# cp www.conf.default www.conf -p
# 生成配置文件
[root@nginx-node php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@nginx-node php-8.3.9]# cd
[root@nginx-node ~]# vim /usr/local/php/etc/php.ini
去掉pid注释
生成启动文件
[root@Nginx-node ~]# cd /root/php-8.3.9/
[root@Nginx-node php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by
this unit.
#ProtectSystem=full #注释该内容
[root@nginx-node php-8.3.9]# systemctl daemon-reload
[root@nginx-node php-8.3.9]# systemctl start php-fpm.service
[root@nginx php-8.3.9]# netstat -antlupe | grep php-fpm
tcp 0 0 0.0.0.0:9000 0.0.0.0:* LISTEN 0 177244 134978/php-fpm: mas
[root@nginx-node ~]# cat /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name var.haha.org;
root /data/php;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
6.3.3php的动态扩展模块(php的缓存模块)
安装memcache模块
[root@Nginx-node ~]# tar zxf memcache-8.2.tgz
[root@Nginx-node ~]# cd memcache-8.2/
[root@Nginx-node memcache-8.2]# yum install autoconf
[root@Nginx-node memcache-8.2]# phpize
[root@Nginx-node memcache-8.2]# ./configure && make && make install
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-nonzts-20230831/
[root@Nginx-node memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-
20230831/
memcache.so opcache.so
[root@Nginx-node ~]# cd memcache-8.2/
[root@Nginx-node memcache-8.2]# cp example.php memcache.php /data/php/
[root@Nginx-node ~]# vim /data/php/memcache.php
配置 php 加载 memcache 模块
[root@Nginx-node ~]# vim /usr/local/php/etc/php.ini
[root@Nginx-node ~]# yum install memcached -y
[root@Nginx-node ~]# systemctl enable --now memcached.service
[root@nginx-node memcache-8.2]# netstat -antlupe | grep memcache
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN 977 352981 276742/memcached
tcp6 0 0 ::1:11211 :::* LISTEN 977 352982 276742/memcached
[root@Nginx-node ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"
测试
6.3.4php高速缓存
部署方法
在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所以nginx需要重新编译
[root@nginx-node nginx-1.26.1]# make clean
rm -rf Makefile objs
[root@nginx-node nginx-1.26.1]# rm -rf /usr/local/nginx/