高性能Web服务端的学习笔记
1 Apache 经典的 Web 服务端
Apache起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发
目前经历了两大版本分别是1.X和2.X
其可以通过编译安装实现特定的功能
1.1 Apache prefork 模型
- 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
- 每个子进程有一个独立的线程响应用户请求
- 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
- 是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.2 Apache worker 模型
- 一种多进程和多线程混合的模型
- 有一个控制进程,启动多个子进程
- 每个子进程里面包含固定的线程
- 使用线程程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,
- 由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在prefork模式下,同样会发生)
1.3 Apache event模型
2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题(某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep-alived类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放缺点:没有线程安全控制
2 Nginx-高性能的 Web 服务端
2.1 服务端 I/O 流程
I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。
一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。
服务器的I/O
- 磁盘I/O
- 网络I/O : 一切皆文件,本质为对socket文件的读写
磁盘 I/O
磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间
网络 I/O
网络通信就是网络协议栈到用户空间进程的IO就是网络IO
网络I/O处理过程
- 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
- 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
- 返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)
不论磁盘和网络I/O
每次I/O,都要经由两个阶段:
- 第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
- 第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
3 Nginx架构
Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器
解决C10K问题(10K Connections)
Nginx官网:http://nginx.org
3.1 Nginx 功能介绍
- 静态的web资源服务器html,图片,js,css,txt等静态资源
- http/https协议的反向代理
- 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
- tcp/udp协议的请求转发(反向代理)
- imap4/pop3协议的反向代理
3.2 基础特性
- 模块化设计,较好的扩展性
- 高可靠性
- 支持热部署:不停机更新配置文件,升级版本,更换日志文件
- 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
- event-driven,aio,mmap,sendfile
3.3 Web 服务相关的功能
- 虚拟主机(server)
- 支持 keep-alive 和管道连接(利用一个连接做多次请求)
- 访问日志(支持基于日志缓冲提高其性能)url rewirte
- 路径别名
- 基于IP及用户的访问控制
- 支持速率限制及并发数限制
- 重新配置和在线升级而无须中断客户的工作进程
3.4 Nginx 架构和进程
3.5 Nginx 进程间通信
3.6 Nginx 启动和 HTTP 连接建立
- Nginx 启动时,Master 进程,加载配置文件
- Master 进程,初始化监听的 socket
- Master 进程,fork 出多个 Worker 进程
- Worker 进程,竞争新的连接,获胜方通过三次握手,建立 Socket 连接,并处理请求
3.7 HTTP 处理过程
3.8 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 版本支持动态装载和卸载
4 Nginx的安装
4.1 Nginx 编译安装
实验环境搭建
vmset.sh eth0 172.25.254.100 nginx-node1.timinglee.org
编译安装:
[root@nginx-node1 ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
[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 --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
[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加密
[root@nginx-node1 nginx-1.24.0]# make && make install
nginx完成安装以后,有四个主要的目录
[root@nginx-node1 nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin
conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀去掉即可。
html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面。
logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比
如/var/logs/nginx里面。
sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
验证版本及编译参数
[root@nginx-node1 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx-node1 ~]# source ~/.bash_profile
[root@nginx-node1 ~]# nginx -V
nginx version: nginx/1.24.0
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
启动nginx:
[root@nginx-node1 ~]# 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 172.25.254.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
关闭debug
[root@nginx-node1 nginx-1.24.0]# vim auto/cc/gcc
# debug
#CFLAGS="$CFLAGS -g"
[root@nginx-node1 ~]# du -sh /usr/local/nginx/sbin/nginx
1.2M /usr/local/nginx/sbin/nginx
4.2 平滑升级和回滚
平滑升级流程
- 将旧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
平滑升级和回滚案例
[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 ~]# ls
公共 视频 文档 音乐 anaconda-ks.cfg echo-nginx-module-0.63.tar.gz nginx-1.24.0.tar.gz
模板 图片 下载 桌面 echo-nginx-module-0.63 nginx-1.24.0 nginx-1.26.2.tar.gz
[root@nginx-node1 ~]# tar zxf nginx-1.26.2.tar.gz
[root@nginx-node1 ~]# cd nginx-1.26.2/
[root@nginx-node1 nginx-1.26.2]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
[root@nginx-node1 nginx-1.26.2]# ./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.2]# make
[root@nginx-node1 nginx]# cd sbin/
[root@nginx-node1 sbin]# ls
nginx
# 备份原先的文件
[root@nginx-node1 sbin]# cp nginx nginx.old
[root@nginx-node1 sbin]# \cp -f /root/nginx-1.26.2/objs/nginx /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2064 ? Ss 00:10 0:00 nginx: master process nginx
nginx 14367 0.0 0.1 14200 5264 ? S 00:10 0:00 nginx: worker process
root 14408 0.0 0.0 221680 2304 pts/0 R+ 00:14 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -USR2 14366
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2576 ? Ss 00:10 0:00 nginx: master process nginx
nginx 14367 0.0 0.1 14200 5264 ? S 00:10 0:00 nginx: worker process
root 14409 0.0 0.1 9764 6528 ? S 00:14 0:00 nginx: master process nginx
nginx 14410 0.0 0.1 14228 5004 ? S 00:14 0:00 nginx: worker process
root 14412 0.0 0.0 221680 2304 pts/0 S+ 00:14 0:00 grep --color=auto nginx
#回收旧的主进程
[root@nginx-node1 sbin]# kill -WINCH 14366
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2576 ? Ss 00:10 0:00 nginx: master process nginx
root 14409 0.0 0.1 9764 6528 ? S 00:14 0:00 nginx: master process nginx
nginx 14410 0.0 0.1 14228 5004 ? S 00:14 0:00 nginx: worker process
root 14414 0.0 0.0 221680 2304 pts/0 S+ 00:16 0:00 grep --color=auto nginx
#已经完成升级
[root@nginx-node1 ~]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.26.2
Date: Thu, 15 Aug 2024 16:18:05 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 16:10:20 GMT
Connection: keep-alive
ETag: "66be286c-267"
Accept-Ranges: bytes
版本回滚
# hup老版本
[root@nginx-node1 sbin]# kill -HUP 14366
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2576 ? Ss 00:10 0:00 nginx: master process nginx
root 14409 0.0 0.1 9764 6528 ? S 00:14 0:00 nginx: master process nginx
nginx 14410 0.0 0.1 14228 5260 ? S 00:14 0:00 nginx: worker process
nginx 14420 0.0 0.1 14200 5008 ? S 00:21 0:00 nginx: worker process
root 14422 0.0 0.0 221812 2304 pts/0 S+ 00:21 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -WINCH 14409
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2576 ? Ss 00:10 0:00 nginx: master process nginx
root 14409 0.0 0.1 9764 6528 ? S 00:14 0:00 nginx: master process nginx
nginx 14420 0.0 0.1 14200 5008 ? S 00:21 0:00 nginx: worker process
[root@nginx-node1 ~]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Thu, 15 Aug 2024 16:23:14 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 16:10:20 GMT
Connection: keep-alive
ETag: "66be286c-267"
Accept-Ranges: bytes
# 把新的备份
[root@nginx-node1 sbin]# cp nginx nginx.new
[root@nginx-node1 sbin]# ls
nginx nginx.new nginx.old
[root@nginx-node1 sbin]# \cp -f nginx.old nginx
[root@nginx-node1 sbin]# kill -9 14409
[root@nginx-node1 sbin]# ps aux | grep nginx
root 14366 0.0 0.0 9864 2576 ? Ss 00:10 0:00 nginx: master process nginx
nginx 14420 0.0 0.1 14200 5264 ? S 00:21 0:00 nginx: worker process
root 14444 0.0 0.0 221680 2304 pts/0 R+ 00:25 0:00 grep --color=auto nginx
nginx命令应用示例:
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
nginx: [emerg] "worker_processes" directive is duplicate in
/usr/local/nginx/conf/nginx.conf:3
2.4.2.4 Nginx 启动文件
2.6 平滑升级和回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时
Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
[root@Nginx ~]# nginx -g "worker_processes 6;"
[root@Nginx ~]# ps aux | grep nginx
root 48148 0.0 0.1 9868 2052 ? Ss 14:00 0:00 nginx: master process nginx -g worker_processes 6;
nobody 48149 0.0 0.2 14200 4868 ? S 14:00 0:00 nginx: worker process
nobody 48150 0.0 0.2 14200 4868 ? S 14:00 0:00 nginx: worker process
nobody 48151 0.0 0.2 14200 4868 ? S 14:00 0:00 nginx: worker process
[root@Nginx ~]# nginx -s quit
[root@Nginx ~]# ps aux | grep nginx
root 48171 0.0 0.1 221664 2176 pts/0 S+ 14:04 0:00 grep --
color=auto nginx
#前台运行
[root@Nginx ~]# nginx -g "daemon off;"
常用参数
[root@Nginx ~]# nginx -v
nginx version: nginx/1.18.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-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: /etc/nginx/) #指定Nginx 目录
-c filename : set configuration file (default: /etc/nginx/nginx.conf) #配置文件路径
-g directives : set global directives out of configuration file #设置全局指令,注意和配置文件不要同时配置,否则冲突
4.3 nginx启动文件脚本
[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
[root@nginx-node1 sbin]# systemctl daemon-reload
[root@nginx-node1 sbin]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
5 nginx全局配置参数优化调整
5.1 全局配置
Main 全局配置段常见的配置指令分类
- 正常运行必备的配置
- 优化性能相关的配置
- 用于调试及定位问题相关的配置
- 事件驱动相关的配置
配置调优
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
worker_cpu_affinity 0001 0010 0100 1000;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 100000;
}
修改最大打开文件
[root@nginx-node1 logs]# ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 14261
max locked memory (kbytes, -l) 8192
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 14261
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@nginx-node1 logs]# vim /etc/security/limits.conf
# End of file
nginx - nofile 100000
[root@nginx-node1 logs]# sudo -u nginx ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 14261
max locked memory (kbytes, -l) 8192
max memory size (kbytes, -m) unlimited
open files (-n) 100000 #
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 14261
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@nginx-node1 ~]# nginx -s reload
5.2 新建一个 PC web 站点
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
events {
worker_connections 100000;
use epoll;
}
#gzip on;
includ "/usr/local/nginx/conf.d/*.conf";
[root@nginx-node1 ~]# mkdir -p /usr/local/nginx/conf.d
[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
5.3 root 与 alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location
[root@nginx-node1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
location /test1/{
root /data/web;
}
}
[root@nginx-node1 ~]# nginx -s reload
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于location上下文,此指令使用较少
alias示例:
[root@nginx-node1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
location /test1/ {
root /data/web;
}
location /test2 {
alias /data/web/test1;
}
}
[root@nginx-node1 ~]# nginx -s reload
5.4 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前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号
#匹配优先级从高到低:
=, ^~, ~/~*, 不带符号
5.5 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 lee
New password:
Re-type new password:
Adding password for user lee
[root@nginx-node1 ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$gIWhdA.b$zvMJBzqCLMapGmNkV0bAu1
lee:$apr1$lM5Z63dU$72KemqzJKhXaZvZwPzZCN0
[root@nginx-node1 ~]# mkdir /data/web/lee
[root@nginx-node1 ~]# echo lee > /data/web/lee/index.html
[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 /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
}
5.6 nginx自定义错误页面
自定义错误页,同时也可以用指定的响应状态码进行响应, 可用位置:http, server, location, if in
[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;
location /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# mkdir -p /data/web/errorpage
[root@nginx-node1 ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx-node1 ~]# nginx -s reload
5.7 nginx 自定义错误日志
[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 /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# mkdir /var/log/timinglee.org
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# curl www.timinglee.org
www.timinglee.org
[root@nginx-node1 ~]# cat /var/log/timinglee.org/access.log
172.25.254.1 - admin [19/Aug/2024:00:42:37 +0800] "GET /leea HTTP/1.1" 404 11 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
[root@nginx-node1 ~]# curl www.timinglee.org/adv
error page
[root@nginx-node1 ~]# cat /var/log/timinglee.org/error.log
2024/08/19 00:42:37 [error] 1909#0: *5 open() "/data/web/leea" failed (2: No such file or directory), client: 172.25.254.1, server: www.timinglee.org, request: "GET /leea HTTP/1.1", host: "www.timinglee.org"
5.8 nginx 检测文件是否存在
try_files会按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内部500错误。
[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;
try_files $uri $uri.html $uri/index.html /error/default.html;
location /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# mkdir /data/web/html/error
[root@nginx-node1 ~]# echo error default > /data/web/html/error/default.html
[root@nginx-node1 ~]# curl www.timinglee.org
www.timinglee.org
[root@nginx-node1 ~]# rm -rf /data/web/html/index.html
[root@nginx-node1 ~]# curl www.timinglee.org
error default
5.9 nginx 长链接的管理
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
#keepalive_timeout 0;
keepalive_timeout 5;
keepalive_requests 2;
[root@nginx-node1 ~]# curl -v www.timinglee.org
* Trying 172.25.254.100:80...
* Connected to www.timinglee.org (172.25.254.100) port 80 (#0)
> GET / HTTP/1.1
> Host: www.timinglee.org
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.26.2
< Date: Sun, 18 Aug 2024 17:36:03 GMT
< Content-Type: text/html
< Content-Length: 18
< Last-Modified: Sun, 18 Aug 2024 17:03:56 GMT
< Connection: keep-alive
< ETag: "66c2297c-12"
< Accept-Ranges: bytes
<
www.timinglee.org
* Connection #0 to host www.timinglee.org left intact
[root@nginx-node1 ~]# telnet www.timinglee.org 80
Trying 172.25.254.100...
Connected to www.timinglee.org.
Escape character is '^]'.
GET / HTTP/1.1
Host: www.timinglee.org
HTTP/1.1 200 OK
Server: nginx/1.26.2
Date: Sun, 18 Aug 2024 17:36:21 GMT
Content-Type: text/html
Content-Length: 18
Last-Modified: Sun, 18 Aug 2024 17:03:56 GMT
Connection: keep-alive
ETag: "66c2297c-12"
Accept-Ranges: bytes
www.timinglee.org
Connection closed by foreign host.
5.10 作为下载服务器配置
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 /data/web/download
[root@nginx-node1 ~]# dd if=/dev/zero of=/data/web/download/pzcfile bs=1M count=100
记录了100+0 的读入
记录了100+0 的写出
104857600字节(105 MB,100 MiB)已复制,0.0186036 s,5.6 GB/s
[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;
try_files $uri $uri.html $uri/index.html /error/default.html;
location /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
location /download {
root /data/web
autoindex on;
autoindex_localtime on;
autoindex_exact_size off;
limit_rate 1024k;
}
}
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# wget www.timinglee.org/download/pzcfile
--2024-08-19 01:49:01-- http://www.timinglee.org/download/pzcfile
正在解析主机 www.timinglee.org (www.timinglee.org)... 172.25.254.100
正在连接 www.timinglee.org (www.timinglee.org)|172.25.254.100|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:104857600 (100M) [application/octet-stream]
正在保存至: “pzcfile”
pzcfile 4%[> ] 4.00M 1.01MB/s 剩余 95s
6 nginx的高级配置
6.1 nginx的状态页面
- 基于nginx 模块 ngx_http_stub_status_module 实现,
- 在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module
- 否则配置完成之后监测会是提示法错误
注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态
[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;
}
}
6.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 ~]# cd /usr/local/nginx/conf/
[root@nginx-node1 conf]# 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 conf]# nginx -s reload
[root@nginx-node1 conf]# echo hello world > /data/web/html/samll.html
[root@nginx-node1 conf]# du -sh /usr/local/nginx/logs/access.log
[root@nginx-node1 conf]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html
[root@nginx-node1 conf]# curl --head --compressed 172.25.254.100/big.html
HTTP/1.1 200 OK
Server: nginx/1.26.2
Date: Sun, 18 Aug 2024 18:18:42 GMT
Content-Type: text/html
Last-Modified: Sun, 18 Aug 2024 18:16:58 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/"66c23a9a-11b810"
Content-Encoding: gzip
6.3 Nginx 变量使用
- nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
- 变量可以分为内置变量和自定义变量
- 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
常用内置变量
$remote_addr;
#存放了客户端的地址,注意是客户端的公网IP
$args;
#变量中存放了URL中的所有参数
#例如:https://search.jd.com/Search?keyword=手机&enc=utf-8
#返回结果为: keyword=手机&enc=utf-8
$is_args
#如果有参数为? 否则为空
$document_root;
#保存了针对当前资源的请求的系统根目录,例如:/webdata/nginx/timinglee.org/lee。
$document_uri;
#保存了当前请求中不包含参数的URI,注意是不包含请求的指令
#比如:http://lee.timinglee.org/var?\id=11111会被定义为/var
#返回结果为:/var
$host;
#存放了请求的host名称
limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_port;
#客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口
$remote_user;
#已经经过Auth Basic Module验证的用户名
$request_body_file;
#做反向代理时发给后端服务器的本地资源的名称
$request_method;
#请求资源的方式,GET/PUT/DELETE等
$request_filename;
#当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径,
#如:webdata/nginx/timinglee.org/lee/var/index.html
$request_uri;
#包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args,
#例如:/main/index.do?id=20190221&partner=search
$scheme;
#请求的协议,例如:http,https,ftp等
$server_protocol;
#保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr;
#保存了服务器的IP地址
$server_name;
#虚拟主机的主机名
$server_port;
#虚拟主机的端口号
$http_user_agent;
#客户端浏览器的详细信息
$http_cookie;
#客户端的所有cookie信息
$cookie_<name>
#name为任意请求报文首部字部cookie的key名
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,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;
添加hosts本地解析var.timinglee.org
[root@nginx-node1 conf.d]# vim var.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]# 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
53226
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
自定义变量
假如需要自定义变量名称和值,使用指令set $variable value;
set $name timinglee;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port";
server {
listen 80;
server_name var.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]# curl -b "key1=lee,key2=lee1" -u lee:lee var.timinglee.org/var?name=lee&&id=6666
lee
6.4 nginx中的rewrite模块功能
if 指令
[root@nginx-node1 conf.d]# vim var.conf
[root@nginx-node1 conf.d]# cat var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /var {
default_type text/html;
set $timinglee lee;
echo $remote_addr;
echo $args;
echo $is_args;
echo $document_root;
echo $document_uri;
echo $host;
echo $remote_port;
echo $remote_user;
echo $request_method;
echo $request_filename;
echo $request_uri;
echo $scheme;
echo $server_protocol;
echo $server_addr;
echo $server_name;
echo $server_port;
echo $http_user_agent;
echo $http_cookie;
echo $cookie_key2;
echo $timinglee;
}
location /test2 {
if ( !-e $request_filename ){
echo "$request_filename is not exist";
#return 409;
}
}
}
[root@nginx-node1 conf.d]# curl var.timinglee.org/test2/index.html
/data/web/html/test2/index.html is not exist
# 如果存在就显示内容
break 指令
用于中断当前相同作用域(location)中的其他Nginx配置
与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,
该指令可以在server块和locationif块中使用
location /break {
default_type text/html;
set $name lee;
echo $name;
set $id 66;
echo $id;
[root@nginx-node1 conf.d]# curl var.timinglee.org/break
lee
66
location /break {
default_type text/html;
set $name lee;
echo $name;
break;
set $id 66;
echo $id;
}
[root@nginx-node1 conf.d]# nginx -s reload
[root@nginx-node1 conf.d]# curl var.timinglee.org/break
lee
return 指令
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置
location /return {
default_type text/html;
if ( !-e $request_filename){
return 301 http://www.baidu.com;
}
echo "$request_filename is exist";
}
[root@nginx-node1 conf.d]# curl -I var.timinglee.org/return
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.2
Date: Sun, 18 Aug 2024 19:23:01 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.baidu.com
[root@nginx-node1 conf.d]# mkdir -p /data/web/html/return
[root@nginx-node1 conf.d]# curl -I var.timinglee.org/return
HTTP/1.1 200 OK
Server: nginx/1.26.2
Date: Sun, 18 Aug 2024 19:24:01 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
永久
location / {
root /data/web/var;
index index.html;
rewrite / http://www.timinglee.com permanent;
#rewrite / http://www.timinglee.com redirect;
}
[root@nginx-node1 conf.d]# curl -I var.timinglee.org
HTTP/1.1 301 Moved Permanently
Server: nginx/1.26.2
Date: Sun, 18 Aug 2024 19:28:10 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.timinglee.com
break和last区别案例
[root@nginx-node1 conf.d]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx-node1 conf.d]# echo test1 > /data/web/html/test1/index.html
[root@nginx-node1 conf.d]# echo test2 > /data/web/html/test2/index.html
[root@nginx-node1 conf.d]# echo last > /data/web/html/last/index.html
[root@nginx-node1 conf.d]# echo break > /data/web/html/break/index.html
[root@nginx-node1 conf.d]# vim var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /break {
rewrite ^/break/(.*) /test1/$1;
rewrite ^/test1/(.*) /test2/$1;
}
location /last {
rewrite ^/last/(.*) /test1/$1;
rewrite ^/test1/(.*) /test2/$1;
}
location /test1 {
default_type text/html;
echo "timinglee hhiehiehiaieh";
}
location /test2 {
root /data/web/html;
}
}
全站加密
[root@nginx-node1 conf.d]# cd /usr/local/nginx/
[root@nginx-node1 nginx]# mkdir certs
[root@nginx-node1 nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/timinglee.org.key -x509 -days 365 -out /usr/local/nginx/certs/timinglee.org.crt
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shaanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:timinglee
Organizational Unit Name (eg, section) []:s^Hwebserver
Common Name (eg, your name or your server's hostname) []:www.timinglee.org
Email Address []:admin@timinglee.org
server {
listen 80;
listen 443 ssl;
server_name www.timinglee.org;
root /data/web/html;
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 redirect;
}
}
}
server {
listen 80;
listen 443 ssl;
server_name www.timinglee.org;
root /data/web/html;
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;
}
}
访问错误直接重定向
6.5 防盗链
实现盗链
用一台新主机web10
[root@web10 ~]# dnf install httpd -y
# 编写html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.timinglee.org/images/batman.png" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.timinglee.org>狂点xixi</a>嘿嘿哈哈</p>
</body>
</html>
防盗链
location /images {
valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;
if ( $invalid_referer ){
rewrite ^/ http://www.timinglee.org/superman.jpg;
}
}
7 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协议转发至指定服务器处理
7.1 实现动静分离
需要两台新的主机提供http
[root@nginx-node1 ~]# curl 172.25.254.10
172.25.254.10
[root@nginx-node1 ~]# curl 172.25.254.20
172.25.254.20
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.10
[root@nginx-node1 conf.d]# curl www.timinglee.org/static/
static 172.25.254.20
[root@web10 ~]# vim /var/www/html/index.php
<?php
phpinfo();
?>
[root@nginx-node1 conf.d]# vim vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
location ~ /.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static {
proxy_pass http://172.25.254.20:8080;
}
}
7.2 nginx反向代理的缓存功能
非缓存场景压测
[root@web10 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
准备缓存配置
[root@nginx-node1 conf.d]# vim /usr/local/nginx/conf/nginx.conf
proxy_cache_path /apps/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
[root@nginx-node1 conf.d]# vim vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
location ~ /.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static {
proxy_pass http://172.25.254.20:8080;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
}
}
进行压测
[root@web10 ~]# ab -n1000 -c100 http://www.timinglee.org/static/index.html
Concurrency Level: 100
Time taken for tests: 0.017 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 1000
Total transferred: 394000 bytes
HTML transferred: 196000 bytes
Requests per second: 60565.68 [#/sec] (mean)
Time per request: 1.651 [ms] (mean)
Time per request: 0.017 [ms] (mean, across all concurrent requests)
Transfer rate: 23303.59 [Kbytes/sec] received
反向代理示例: 后端多台web服务器
部署的两台httpd主机
[root@nginx-node1 conf.d]# vim vhosts.conf
upstream webcluster {
#ip_hash;
#hash $request_uri consistent;
#hash $cookie_lee;
#least_conn;
server 172.25.254.10:80 fail_timeout=15s max_fails=3;
server 172.25.254.20:8080 fail_timeout=15s max_fails=3;
server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.timinglee.org;
location ~ / {
proxy_pass http://webcluster;
}
}
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.10
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.20
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.10
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.20
[root@nginx-node1 conf.d]#
[root@nginx-node1 conf.d]# curl www.timinglee.org
172.25.254.10
7.3 负载均衡实例 DNS
注意TCP的负载均衡要写到http的语句外
[root@web10 ~]# dnf install bind -y
[root@web20 ~]# dnf install bind -y
[root@web10 ~]# vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
secroots-file "/var/named/data/named.secroots";
recursing-file "/var/named/data/named.recursing";
// allow-query { localhost; };
dnssec-validation no;
[root@web10 ~]# vim /etc/named.rfc1912.zones
zone "timinglee.org" IN {
type master;
file "timinglee.org.zone";
allow-update { none; };
};
[root@web10 named]# cp named.localhost timinglee.org.zone -p
[root@web10 named]# vim timinglee.org.zone
$TTL 1D
@ IN SOA ns.timinglee.org. root.timinglee.org. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns.timinglee.org.
ns A 172.25.254.10
www A 172.25.254.10
[root@web10 named]# vim timinglee.org.zone
[root@web10 named]# systemctl start named
[root@web10 named]# dig www.timinglee.org @172.25.254.10
; <<>> DiG 9.16.23-RH <<>> www.timinglee.org @172.25.254.10
[root@nginx-node1 conf.d]# vim /usr/local/nginx/conf/nginx.conf
include "/usr/local/nginx/tcpconf.d/*.conf";
http {
7.4 数据库测试
[root@web10 ~]# dnf install mariadb-server -y
[root@web20 ~]# dnf install mariadb-server -y
stream{
upstream dns {
server 172.25.254.10:53 fail_timeout=15s max_fails=3;
server 172.25.254.20:53 fail_timeout=15s max_fails=3;
}
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
[root@web10 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=10
[root@web20 named]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=20
[root@web10 ~]# systemctl start mariadb.service
[root@web10 ~]# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.5.22-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> CREATE USER lee@'%' identified by 'lee';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL ON *.* to lee@'%';
Query OK, 0 rows affected (0.001 sec)
[root@web20 named]# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.5.22-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> CREATE USER lee@'%' identified by 'lee';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL ON *.* to lee@'%';
Query OK, 0 rows affected (0.001 sec)
[root@nginx-node1 tcpconf.d]# vim hosts.conf
stream{
upstream dns {
server 172.25.254.10:53 fail_timeout=15s max_fails=3;
server 172.25.254.20:53 fail_timeout=15s max_fails=3;
}
upstream mysql {
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 3306
proxy_timeout 60s;
proxy_pass mysql;
}
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
# 登录实现mysql负载
8 实现 FastCGI
什么是PHP-FPM?
- PHP-FPM(FastCGI Process Manager:
- FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
- 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server的请求
- worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
源码编译php
root@nginx-node1 ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@nginx-node1 ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@nginx-node1 ~]# cd nginx-1.26.2/
[root@nginx-node1 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-http_gzip_static_module \
> --with-stream \
> --with-stream_ssl_module \
> --with-stream_realip_module \
> --with-pcre
[root@nginx-node1 nginx-1.26.2]# make && make install
[root@nginx-node1 nginx-1.26.2]# nginx
[root@nginx-node1 nginx-1.26.2]# nginx -V
[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 --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-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd
php相关配置优化
[root@nginx-node1 etc]# cd /usr/local/php/etc/
[root@nginx-node1 etc]# ls
php-fpm.conf.default php-fpm.d
[root@nginx-node1 etc]# cp -p 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]# ls
www.conf.default
[root@nginx-node1 php-fpm.d]# cp -p www.conf.default www.conf
[root@nginx-node1 php-fpm.d]# vim 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]# cd /usr/local/php/etc/
[root@nginx-node1 etc]# vim php.ini
date.timezone = Asia/Shanghai
[root@nginx-node1 php-8.3.9]# cd sapi/fpm/
[root@nginx-node1 fpm]# cp php-fpm.service /lib/systemd/system/
cp:是否覆盖'/lib/systemd/system/php-fpm.service'? yes
[root@nginx-node1 fpm]# pwd
/root/php-8.3.9/sapi/fpm
[root@nginx-node1 fpm]# vim /lib/systemd/system/php-fpm.service # 注释readonly下面
[root@nginx-node1 fpm]# systemctl daemon-reload
[root@nginx-node1 fpm]# systemctl start php-fpm
nignx和php的整合
[root@nginx-node1 conf.d]# mkdir /data/web/php -p
[root@nginx-node1 conf.d]# cat index.php #php测试页面
<?php
phpinfo();
?>
[root@nginx-node1 conf.d]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
location ~ \.php$ {
root /data/web/php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
nginx-php的缓存优化
[root@nginx-node1 ~]# tar zxf memcache-8.2.tgz
[root@nginx-node1 ~]# cd memcache-8.2/
[root@nginx-node1 memcache-8.2]# phpize
Configuring for:
PHP Api Version: 20200930
Zend Module Api No: 20200930
Zend Extension Api No: 420200930
[root@nginx-node1 memcache-8.2]# ./configure && make && make install
[root@nginx-node1 memcache-8.2]# vim /usr/local/php/etc/php.ini
;zend_extension=opcache
extension=memcache
[root@nginx-node1 memcache-8.2]# yum install memcached -y
性能对比
Concurrency Level: 10
Time taken for tests: 0.135 seconds
Complete requests: 1000
Failed requests: 911
Concurrency Level: 10
Time taken for tests: 0.142 seconds
Complete requests: 1000
Failed requests: 104
php高速缓存
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name php.timinglee.org;
root /data/php;
location /memc {
internal;
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
set $memc_key $query_string; #使用内置变量$query_string来作为key
set $memc_exptime 300; #缓存失效时间300秒
memc_pass memcache;
}
location ~ \.php$ {
set $key $uri$args; #设定key的值
srcache_fetch GET /memc $key; #检测mem中是否有要访问的php
srcache_store PUT /memc $key; #缓存为加载的php数据
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
9 nginx 二次开发版本
编译安装 openresty
[root@nginx-node1 openresty-1.25.3.1]# tar zxf openresty-1.25.3.1.tar.gz
[root@nginx-node1 openresty-1.25.3.1]# cd openresty-1.25.3.1/
[root@nginx-node1 openresty-1.25.3.1]# ./configure --prefix=/usr/local/openresty/nginx --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --without-pcre2 --with-stream_ssl_preread_module
[root@nginx-node1 openresty-1.25.3.1]# gmake -j2 && gmake install
[root@nginx-node1 bin]# pwd
/usr/local/openresty/nginx/bin
[root@nginx-node1 bin]# vim ~/.bash_profile
[root@nginx-node1 bin]# source ~/.bash_profile
[root@nginx-node1 bin]# openresty
[root@nginx-node1 bin]# netstat -antlulpe | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 241066 210575/nginx: maste
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 24666 980/sshd: /usr/sbin
tcp6 0 0 :::22 :::* LISTEN 0 24668 980/sshd: /usr/sbin