1.web服务基础介绍
正常情况下单次web服务访问流程
1.1web服务介绍
1.1.1Apache经典的web服务端
Apache起初由美国的伊利诺伊大学香槟分校的国家超级计算机应用中心开发
目前经历了两大版本分别是1.X和2.X
其可以通过编译安装实现特定的功能
1.1.1.1Apache prefork模型
-
预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
-
每个子进程有一个独立的线程响应用户请求
-
相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
-
是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.1.1.2Apache worker模型
-
一种多进程和多线程混合的模型
-
有一个控制进程,启动多个子进程
-
每个子进程里面包含固定的线程
-
使用线程程来处理请求
-
当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,
-
由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
1.1.1.3 Apache event模型
-
Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll) 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
-
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
-
event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
-
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
1.1.2Nginx-高性能的web服务端
Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发 工作最早从2002年开始,第一次公开发布时间是2004年10月4日,版本号是0.1.0
基于Nginx的工作场景:
1.1.3用户访问体验和性能
影响用户体验的因素
1.客户端
-
客户端硬件配置
-
客户端网络速率
-
客户端与服务端距离
2.服务器
-
服务端网络速率
-
服务端硬件配置
-
服务端架构设计
-
服务端应用程序工作模式
-
服务端并发数量服务端响应文件大小及数量 buffer cache
-
服务端I/O压力1.2.4 服务端 I/O 流程
1.1.4服务端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文件的读写
1.1.4.1 磁盘 I/O
磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相 应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存, 如果是比较大的数据也需要等待时间
1.1.4.2 网络I/O
网络I/O 处理过程
-
获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3)
-
构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4)
-
返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)
不论磁盘和网络I/O
每次I/O,都要经由两个阶段:
-
第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
-
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
1.2 I/O 模型
同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状 态的通知。
-
同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事 情是否处理完成
-
异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
-
阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂 起,干不了别的事情
-
非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完 成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
1.2.2 网络I/O模型
阻塞型、非阻塞型、复用型、信号驱动型、异步
1.2.2.1 阻塞型 I/O 模型(blocking IO)
-
阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
-
用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然 后将接收的数据拷贝到用户空间,完成read操作
-
用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线 程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够
优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销 较apache 的preforck使用的是这种模式。
同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进 程将一直等待并不再接受新的请求,并由进程轮询查看I/O是否完成,完成后进程将I/O结果返回给 Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种 方式简单,但是比较慢,用的比较少。
1.2.2.2 非阻塞型 I/O 模型 (nonblocking IO)
上图可以看到,用户线程发起io请求时立即返回,但是并未读取到任何数据,在此期间,用户线程不断地发起io请求,直到数据真正到达后,才真正读取到数据,继续执行,而在等待回应的过程中,程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结 果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完 成。
但是一旦返回了结果,那么用户进程将会甩掉其他请求,等待此请求的用户数据响应,直到返回数据成功
当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实 际使用很少
I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个 process就可以同时处理多个网络连接的IO。
它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数 据到达了,就通知用户进程。
Apache prefork是此模式的select,worker是poll模式。
nginx使用epoll模式
select
假如有多个请求,调用select来处理多个请求,按照序号排列成如图表格,它按照序号依次处理,比如,1.2.3.4.5.6.7.8.9.10,有是个请求,它就会从1开始处理,到10结束,这样循环,如果1没有响应完成,那么就会到2...在此过程中,1可能会成功响应,那么就浪费了1的处理时间,而且select最高可处理1024个请求
poll
和select的区别是poll可以处理无限个请求
epoll
它利用hash运算,它只记录谁响应完成,然后处理就处理
优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述 符一个线程),这样可以大大节省系统资源
缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理 需要 2 次系统调用,占用时间会有增加
IO多路复用适用如下场合:
-
当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用
-
当一个客户端同时处理多个套接字时,此情况可能的但很少出现
-
当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
-
当一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
-
当一个服务器要处理多个服务或多个协议,一般要使用I/O复用
1.2.2.4 信号驱动式 I/O 模型 (signal-driven IO)
信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知 进程。
在内核准备好数据之前,是非阻塞的,可以处理其他的请求,但是内核准备完数据后救护发送信号通知进程,进程过来等待进入阻塞,不再处理其他请求,直到数据拷贝完成
优 点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此 可以提高资源的利用率
缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程 请求后 进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。
1.2.2.5 异步 I/O 模型 (asynchronous IO)
异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O 是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把 等待上菜的时间也给省了
全程非阻塞
用户进程进行aio_read系统调用之后,无论内核数据是否准备 好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直 接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。
1.3零拷贝
1.3.1传统LInux中I/O的问题
1.3.2 什么是零拷贝
零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做 到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化
1.3.3 零拷贝相关技术
1.3.3.1 MMAP ( Memory Mapping )
就是磁盘文件拷贝文件到内核Kernel缓存区,kernel缓存区和user缓存区通过MMAP技术相当于是建立了软链接,然后他俩之间就实现了共享内存,所以kernel缓存区可以不用拷贝到user缓存区,
mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间 后,进程可以向访问普通内存一样对文件进行访问。 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘 地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
1.3.3.2 SENDFILE
就相当于不经过user缓存区,直接在内核里面进行拷贝,其实就是把kernel缓存区和socket缓存区的东西都映射到可user缓存区,这样就节省可内核与用户之间的拷贝
1.3.3.3DMA辅助的SENDFILE
2.nginx架构和安装
2.1nginx介绍
2.1.1 nginx功能介绍
-
静态的web资源服务器html,图片,js,css,txt等静态资源
-
http/https协议的反向代理
-
结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
-
tcp/udp协议的请求转发(反向代理)
-
imap4/pop3协议的反向代理
2.2 nginx架构和进程
2.2.1 nginx进程架构
web请求处理机制
-
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直 到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务 器资源耗尽而无法提供请求
-
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程和此客 户端进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器 对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可 以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作 了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
Nginx是多进程组织模型,而且是一个由Master主进程和Worker工作进程组成。
2.2.2 nginx进程通信
2.3nginx模块介绍
nginx 有多种模块
-
核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件 驱动机制 、进程管理等核心功能
-
标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应 头设置 等等
-
可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash
-
多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
-
邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的 支持
-
Stream服务模块: 实现反向代理功能,包括TCP协议代理
-
第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支 持等
2.4nginx安装
2.4.1nginx的源码编译安装
[root@nginx1 ~]# rz -E //将nginx-1.24.0.tar.gz拖至家目录
rz waiting to receive.
[root@nginx1 ~]# ls
anaconda-ks.cfg nginx-1.24.0.tar.gz
[root@nginx1 ~]# tar zxf nginx-1.24.0.tar.gz //解压
[root@nginx1 ~]# ls
anaconda-ks.cfg nginx-1.24.0 nginx-1.24.0.tar.gz
[root@nginx1 ~]# cd nginx-1.24.0/
[root@nginx1 nginx-1.24.0]#
[root@nginx1 nginx-1.24.0]# ls
auto CHANGES.ru configure html man src
CHANGES conf contrib LICENSE README
###configure 环境检测
[root@nginx1 nginx-1.24.0]#dnf install gcc pcre-devel zlib-devel openssl-devel -y
[root@nginx1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
> --user=nginx \
> --group=nginx \
> --with-http_ssl_module \
> --with-http_v2_module \
> --with-http_realip_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --with-pcre \
> --with-stream \
> --with-stream_ssl_module \
> --with-stream_realip_module
#####这些用来检测当前的环境是否适合这些选择
[root@nginx1 nginx-1.24.0]# make && make install
####nginx安装完成后,有四个主要目录
[root@nginx1 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@nginx1 nginx-1.24.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@nginx1 nginx-1.24.0]# cd /usr/local/nginx/
[root@nginx1 nginx]# ls
conf html logs sbin
[root@nginx1 nginx]# cd sbin/
[root@nginx1 sbin]# ls
nginx
[root@nginx1 sbin]# cd
[root@nginx1 ~]# cd /usr/local/nginx/sbin/
[root@nginx1 sbin]# ls
nginx
[root@nginx1 sbin]# /usr/local/nginx/sbin/nginx
nginx: [emerg] getpwnam("nginx") failed
[root@nginx1 sbin]# useradd -s /sbin/nologin -M nginx
[root@nginx1 sbin]# id nginx
uid=1002(nginx) gid=1002(nginx) groups=1002(nginx)
[root@nginx1 sbin]# ll
total 5516
-rwxr-xr-x 1 root root 5646216 Aug 15 19:56 nginx
[root@nginx1 sbin]# ./nginx
[root@nginx1 sbin]# ps aux | grep nginx
root 15850 0.0 0.0 9864 2052 ? Ss 20:02 0:00 nginx: master process ./nginx
nginx 15851 0.0 0.1 14196 4868 ? S 20:02 0:00 nginx: worker process
root 15855 0.0 0.0 221664 2176 pts/0 S+ 20:03 0:00 grep --color=auto nginx
[root@nginx1 sbin]# /usr/local/nginx/sbin/nginx -s stop
[root@nginx1 sbin]# netstat -autlupe | grep nginx
tcp 0 52 nginx1.exam.com:ssh 172.25.250.1:54272 ESTABLISHED root 27612 1926/sshd: root [pr
[root@nginx1 sbin]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx1 sbin]# source ~/.bash_profile
[root@nginx1 sbin]# nginx
[root@nginx1 sbin]# cd /usr/local/nginx/
[root@nginx1 nginx]# ls
client_body_temp fastcgi_temp logs sbin uwsgi_temp
conf html proxy_temp scgi_temp
[root@nginx1 nginx]# cd conf/
[root@nginx1 conf]# ls
fastcgi.conf koi-win scgi_params
fastcgi.conf.default mime.types scgi_params.default
fastcgi_params mime.types.default uwsgi_params
fastcgi_params.default nginx.conf uwsgi_params.default
koi-utf nginx.conf.default win-utf
[root@nginx1 conf]# curl -I 172.25.250.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Thu, 15 Aug 2024 12:14:10 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 11:56:42 GMT
Connection: keep-alive
ETag: "66bdecfa-267"
Accept-Ranges: bytes
####使用安装完成的二进制文件nginx
[root@Nginx ~]# nginx -v
-?,-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 #设置全局指令,注意和配置文件不要同时配置,否则冲突
2.5 nginx的平滑升级及版本回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时 Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
[root@nginx1 ~]#tar zxf nginx-1.26.1.tar.gz
[root@nginx1 ~]#cd nginx-1.26.1/
[root@nginx1 nginx-1.26.1]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@nginx1 nginx-1.26.1]# cd objs/
[root@nginx1 objs]# ls
autoconf.err nginx ngx_auto_config.h ngx_modules.c src
Makefile nginx.8 ngx_auto_headers.h ngx_modules.o
[root@nginx1 objs]# cd /usr/local/nginx/sbin/
[root@nginx1 sbin]# ls
nginx
[root@nginx1 sbin]# cp nginx nginx.old ####把之前旧的版本拷贝为nginx.old
[root@nginx1 sbin]# ls
nginx nginx.old
[root@nginx1 sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/nginx ###把新版本的nginx命令复制过去 \cp -f 强制覆盖不提示
[root@nginx1 sbin]# ps ax | grep nginx ###可以看到原来的版本的进程以及master
15895 ? Ss 0:00 nginx: master process nginx
15896 ? S 0:00 nginx: worker process
19036 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# pidof nginx
15896 15895
[root@nginx1 sbin]# kill -USR2 15895
#USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的
nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进
程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
[root@nginx1 sbin]# ps ax | grep nginx ###可以看到新版本旧版本的都在这里
15895 ? Ss 0:00 nginx: master process nginx
15896 ? S 0:00 nginx: worker process
19040 ? S 0:00 nginx: master process nginx
19041 ? S 0:00 nginx: worker process
19043 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# kill -WINCH 15895 ###回收旧版本
[root@nginx1 sbin]# ps ax | grep nginx
15895 ? Ss 0:00 nginx: master process nginx
19040 ? S 0:00 nginx: master process nginx
19041 ? S 0:00 nginx: worker process
19052 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# curl -I 172.25.250.100
HTTP/1.1 200 OK
Server: nginx/1.26.1 ###新版本生效了
Date: Thu, 15 Aug 2024 12:40:35 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 11:56:42 GMT
Connection: keep-alive
ETag: "66bdecfa-267"
Accept-Ranges: bytes
#回滚
#如果升级的版本发现问题需要回滚,可以重新拉起旧版本的worker
[root@nginx1 sbin]# kill -HUP 15895 ##激活旧版本
[root@nginx1 sbin]# ps ax | grep nginx
15895 ? Ss 0:00 nginx: master process nginx
19040 ? S 0:00 nginx: master process nginx
19041 ? S 0:00 nginx: worker process
19054 ? S 0:00 nginx: worker process
19056 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# kill -WINCH 19040 ###回收新版本
[root@nginx1 sbin]# ps ax | grep nginx
15895 ? Ss 0:00 nginx: master process nginx
19040 ? S 0:00 nginx: master process nginx
19054 ? S 0:00 nginx: worker process
19058 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# curl -I 172.25.250.100
HTTP/1.1 200 OK
Server: nginx/1.24.0 ###旧版本生效,滚回完成
Date: Thu, 15 Aug 2024 12:42:47 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Thu, 15 Aug 2024 11:56:42 GMT
Connection: keep-alive
ETag: "66bdecfa-267"
Accept-Ranges: bytes
[root@nginx1 sbin]# cp nginx nginx.new ###将新版本的复制一份,因为目前的nginx里面是新版本的内容,现在已经激活了旧版本,就需要把旧版本的再复制回去,旧版本之前复制到了nginx.old
[root@nginx1 sbin]# ls
nginx nginx.old nginx.new
[root@nginx1 sbin]# \cp -f nginx.old nginx ###复制旧版本的回nginx
[root@nginx1 sbin]# ps ax | grep nginx
15895 ? Ss 0:00 nginx: master process nginx
19040 ? S 0:00 nginx: master process nginx
19054 ? S 0:00 nginx: worker process
19078 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]# kill -9 19040 ###完全清除新版本的进程
[root@nginx1 sbin]# ps ax | grep nginx
15895 ? Ss 0:00 nginx: master process nginx
19054 ? S 0:00 nginx: worker process
19080 pts/0 S+ 0:00 grep --color=auto nginx
[root@nginx1 sbin]#
2.6设置开机启动脚本
[root@nginx1 sbin]# cat /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@nginx1 sbin]# systemctl daemon-reload
[root@nginx1 sbin]# nginx -s stop
[root@nginx1 sbin]# ps aux | grep nginx
root 19227 0.0 0.0 221664 2176 pts/0 S+ 21:58 0:00 grep --color=auto nginx
[root@nginx1 sbin]# systemctl enable --now nginx.service
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[root@nginx1 sbin]# ps aux | grep nginx
root 19272 0.0 0.0 9864 2052 ? Ss 21:58 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 19273 0.0 0.1 14196 4996 ? S 21:58 0:00 nginx: worker process
root 19275 0.0 0.0 221664 2176 pts/0 S+ 21:58 0:00 grep --color=auto nginx
3.nginx全局配置参数优化调整
[root@nginx1 sbin]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx1 sbin]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx1 sbin]# vim /etc/security/limits.conf
3.1nginx配置中的root和alisa
[root@nginx1 sbin]# vim /usr/local/nginx/conf/nginx.conf
创建文件
[root@nginx1 sbin]# mkdir -p /usr/local/nginx/conf.d
[root@nginx1 sbin]# vim /usr/local/nginx/conf.d/
[root@nginx1 sbin]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx1 sbin]# mkdir -p /data/web/html
[root@nginx1 sbin]# echo www.timinglee.org > /data/web/html/index.html
[root@nginx1 sbin]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
}
然后Windows下做解析,浏览器访问www.timinglee.org
3.1.1 root和alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于 location上下文,此指令使用较少
alias、root示例
[root@nginx1 sbin]# mkdir -p /data/web/test1
[root@nginx1 sbin]# echo /data/web/test1/ > /data/web/test1/index.html
###root示例
[root@nginx1 sbin]# 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@nginx1 sbin]# nginx -s reload
##重启nginx并访问测试
curl www.timinglee.org/test1 会返回/data/web/test1/
###alias示例
[root@nginx1 sbin]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx1 sbin]# 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/test1;
}
location /test2 {
alias /data/web/test1;
}
}
[root@nginx1 sbin]# nginx -s reload
####重启nginx并访问测试
curl www.timinglee.org/test1 会返回/data/web/test1/
3.2location 的详细使用
-
在一个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前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号
#匹配优先级高到低
目录:(~* 或者 ~)> 不带符号 > ^~ > = = 不能指定目录所以排在最后
文件: = > (~*或者~) > 不带符号 > ^~
4.核心配置示例
4.1nginx账户认证功能
由 ngx_http_auth_basic_module 模块提供此功能
[root@nginx1 ~]# yum install httpd-tools -y
[root@nginx1 ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx1 ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$BlZq.ujj$PGTDc1Yrkr/JkrGlWx2ul.
[root@nginx1 ~]# htpasswd -m /usr/local/nginx/.htpasswd lee ##这里再次创建不能-cm,只能-m,不然就会覆盖原来的内容
New password:
Re-type new password:
Adding password for user lee
[root@nginx1 ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$BlZq.ujj$PGTDc1Yrkr/JkrGlWx2ul.
lee:$apr1$bpM9bexv$0NVDyUxCxV3/oS.16iils0
[root@nginx1 ~]# cat /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";
}
}
[root@nginx1 ~]# mkdir /data/web/lee -p
[root@nginx1 ~]# echo lee > /data/web/lee/index.html
[root@nginx1 ~]# nginx -s reload
测试
4.2自定义错误界面
[root@nginx1 ~]# cat /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@nginx1 ~]# mkdir -p /data/web/errorpage
[root@nginx1 ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx1 ~]# nginx -s reload
测试
4.3自定义错误日志
[root@nginx1 ~]# cat /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;
access_log /var/log/nginx/access.log; ######
error_log /var/log/nginx/error.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 ~]# mkdir "/var/log/nginx" -p
[root@nginx1 ~]# curl www.timinglee.org/www
error page
[root@nginx1 ~]# cat /var/log/nginx/access.log
172.25.250.100 - - [16/Aug/2024:14:35:38 +0800] "GET /www HTTP/1.1" 404 11 "-" "curl/7.76.1"
172.25.250.100 - - [16/Aug/2024:14:37:56 +0800] "GET / HTTP/1.1" 200 18 "-" "curl/7.76.1"
172.25.250.100 - - [16/Aug/2024:14:38:02 +0800] "GET /www HTTP/1.1" 404 11 "-" "curl/7.76.1"
[root@nginx1 ~]# cat /var/log/nginx/error.log
2024/08/16 14:35:38 [error] 20252#0: *17 open() "/data/web/html/www" failed (2: No such file or directory), client: 172.25.250.100, server: www.timinglee.org, request: "GET /www HTTP/1.1", host: "172.25.250.100"
2024/08/16 14:38:02 [error] 20252#0: *19 open() "/data/web/html/www" failed (2: No such file or directory), client: 172.25.250.100, server: www.timinglee.org, request: "GET /www HTTP/1.1", host: "www.timinglee.org"
测试
4.4 长连接配置
keepalive_timeout timeout [header_timeout];
#设定保持连接超时时长,0表示禁止长连接, 默认为75s
#通常配置在http字段作为站点全局配置
keepalive_requests 数字;
#在一次长连接上所允许请求的资源的最大数量
#默认为100次,建议适当调大,比如:500
vim /usr/local/nginx/conf/nginx.conf
下载测试工具
dnf install telnet -y
测试
4.5nginx下载服务器
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@nginx1 ~]# cat /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;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
try_files $uri $uri.html $uri/index.html /error/default.html;
location /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@nginx1 ~]# mkdir /data/web/download
[root@nginx1 ~]# dd if=/dev/zero of=/data/web/download/leefile bs=1M count=100
[root@nginx1 ~]# nginx -s reload
测试
5.nginx高级配置
5.1 nginx状态页
基于nginx 模块 ngx_http_stub_status_module 实现,
在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module ,否则配置完成之后监测会是提示法错误
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/status.conf
[root@nginx1 ~]# cat /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.250.1;
deny all;
}
}
[root@nginx1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.100 nginx1.exam.com
172.25.250.100 www.timinglee.org status.timinglee.org
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# curl status.timinglee/org ##linux下访问不了,只有172.25.250.1可以访问
curl: (6) Could not resolve host: status.timinglee
然后在Windows下面做本地解析
测试
5.2nginx的压缩功能
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@nginx1 ~]# 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@nginx1 ~]# echo hello luohailin > /data/web/html/small.html
[root@nginx1 ~]# du -sh /usr/local/nginx/logs/access.log
8.0K /usr/local/nginx/logs/access.log
[root@nginx1 ~]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html
[root@nginx1 ~]# nginx -s reload
##测试
[root@nginx1 ~]# curl --head --compressed 172.25.250.100/big.html
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 08:23:28 GMT
Content-Type: text/html
Last-Modified: Fri, 16 Aug 2024 08:21:05 GMT
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding
ETag: W/"66bf0bf1-1ed8"
Content-Encoding: gzip
[root@nginx1 ~]# curl --head --compressed 172.25.250.100/small.html
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 08:23:44 GMT
Content-Type: text/html
Content-Length: 16
Last-Modified: Fri, 16 Aug 2024 08:19:45 GMT
Connection: keep-alive
Keep-Alive: timeout=60
ETag: "66bf0ba1-10"
Accept-Ranges: bytes
[root@nginx1 ~]# du -sh /data/web/html/small.html
4.0K /data/web/html/small.html
[root@nginx1 ~]# du -sh /data/web/html/big.html
8.0K /data/web/html/big.html
注意:
不是对文件本身进行压缩,是在传输过程中压缩传输过去,然后传输完了之后的文件大小是不变的
5.3自定义变量和内置变量
nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
变量可以分为内置变量和自定义变量
内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
5.3.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名
$http_<name>
#name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有横线需要替换为下划线
示例
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/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;
}
}
[root@nginx1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.100 nginx1.exam.com
172.25.250.100 www.timinglee.org status.timinglee.org var.timinglee.org
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# curl -b "key1=lee,key2=lee1" -u lee:lee var.timinglee.org/var?name=lee&&id=6666172.25.250.100
name=lee
?
/data/web/html
/var
var.timinglee.org
56938
lee
GET
/data/web/html/var
/var?name=lee
http
HTTP/1.1
172.25.250.100
var.timinglee.org
80
curl/7.76.1
key1=lee,key2=lee1
lee1
lee
5.3.2自定义变量
假如需要自定义变量名称和值,使用指令set $variable value;
示例
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
server {
listen 80;
server_name www.timinglee.org;
root /webdata/nginx/timinglee.org/lee;
location /var {
default_type text/html;
set $name timinglee; ###自定义变量
echo $name;
set $web_port $server_port;
echo $web_port;
}
}
测试输出
[root@nginx ~]# curl www.timinglee.org/var
timinglee
80
6.nginx rewrite相关功能以及ngx_http_rewrite_module 模块指令
6.1 if指令
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行 配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断
= #比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false
!= #比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false
~ #区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~ #区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假
~* #不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假
!~* #不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真
-f 和 !-f #判断请求的文件是否存在和是否不存在
-d 和 !-d #判断请求的目录是否存在和是否不存在
-x 和 !-x #判断文件是否可执行和是否不可执行
-e 和 !-e #判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接)
#注意:
#如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
#nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /test2 {
if ( !-e $request_filename ){
echo "$request_filename is not exit";
}
}
##如果不存在test2
[root@nginx1 ~]# curl var.timinglee.org/test2/index.html
/data/web/html/test2/index.html is not exit
##如果存在test2
[root@nginx1 ~]# mkdir /data/web/html/test2 -p
[root@nginx1 ~]# echo test2 > /data/web/html/test2/index.html
[root@nginx1 ~]# curl var.timinglee.org/test2/index.html
test2
6.2 set 指令
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key 另外set定义格式为set $key value,value可以是text, variables和两者的组合。
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /break {
default_type text/html;
set $name ren;
echo $name;
set $id 666;
echo $id;
}
}
[root@nginx1 ~]# curl var.timinglee.org/break
ren
666
6.3 break指令
用于中断当前相同作用域(location)中的其他Nginx配置
与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效
位于后面的 ngx_http_rewrite_module 模块中指令就不再执行
Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,、
该指令可以在server块和locationif块中使用注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /break {
default_type text/html;
set $name ren;
echo $name;
break;
set $id 666;
echo $id;
}
}
[root@nginx1 ~]# curl var.timinglee.org/break
ren
if和break联用
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /break {
default_type text/html;
set $name ren;
echo $name;
if ( $http_user_agent = "curl/7.76.1" ){ ##指定浏览器
break;
}
set $id 666;
echo $id;
}
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# curl var.timinglee.org/break
ren
##换一个浏览器访问if不生效
[root@nginx1 ~]# curl -A "firefox" var.timinglee.org/break
ren
666
6.4return指令
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重 定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配 置都将不被执行,return可以在server、if 和 location块进行配置
示例
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /return {
default_type text/html;
if ( !-e $request_filename ){
return 301 http://www.baidu.com; ##如果不存在,重定向到www.baidu.com
}
echo "$request_filename is exist"; ##如果存在,输出is exist
}
}
[root@nginx1 ~]# nginx -s reload
##如果不存在return
[root@nginx1 ~]# curl -I var.timinglee.org/return
HTTP/1.1 301 Moved Permanently ##301重定向
Server: nginx/1.24.0
Date: Sun, 18 Aug 2024 13:13:24 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.baidu.com
##如果存在return
[root@nginx1 ~]# mkdir -p /data/web/html/return
[root@nginx1 ~]# curl -I var.timinglee.org/return
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Sun, 18 Aug 2024 13:14:35 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding
6.5.rewrite指令
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配, rewrite主要是针对用户请求的URL或者是URI做具体处理
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 这几个字母以外的任意字符
flag说明
redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作
#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,
#而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
6.5.1rewrite案列:域名永久与临时重定向
域名的临时的调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳 转,这种情况浏览器不会缓存跳转,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。 示例: 因业务需要,将访问源域名 www.timinglee.org 的请求永久重定向到 www.timinglee.com
示例
##临时重定向 302
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
#rewrite / http://www.timinglee.com permanent;
rewrite / http://www.timinglee.com redirect;
}
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# curl -I var.timinglee.org
HTTP/1.1 302 Moved Temporarily ##302临时重定向
Server: nginx/1.24.0
Date: Sun, 18 Aug 2024 13:39:22 GMT
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.timinglee.com
##永久重定向 301
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
rewrite / http://www.timinglee.com permanent;
#rewrite / http://www.timinglee.com redirect;
}
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# curl -I var.timinglee.org
HTTP/1.1 301 Moved Permanently ##301永久重定向
Server: nginx/1.24.0
Date: Sun, 18 Aug 2024 13:40:44 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.timinglee.com
6.5.2 rewrite案列:break和last
示例
[root@nginx1 ~]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx1 ~]# echo test1 > /data/web/html/test1/index.html
[root@nginx1 ~]# echo test2 > /data/web/html/test2/index.html
[root@nginx1 ~]# echo break > /data/web/html/break/index.html
[root@nginx1 ~]# echo last > /data/web/html/last/index.html
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/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 "hhhhhhhhhhhh";
}
location /test2 {
root /data/web/html;
}
}
[root@nginx1 ~]# nginx -s reload
测试
示例2
server {
listen 80;
server_name var.timinglee.org;
root /data/web/html;
index index.html;
location /break {
root /data/web/html;
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1;
}
location /last {
rewrite ^/last/(.*) /test1/$1 lats;
rewrite ^/test1/(.*) /test2/$1;
}
location /test1 {
default_type text/html;
return 666 "hhhhhhhhhhhh";
}
location /test2 {
root /data/web/html;
}
}
[root@nginx1 ~]# nginx -s reload
测试
6.5.3 rewrite案例: 自动跳转 https
[root@nginx1 ~]# cd /usr/local/nginx/
[root@nginx1 nginx]# mkdir certs ##建立认证,目录
[root@nginx1 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
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
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;
rewrite /(.*) https://$host/$1 redirect; ##如果这样写,那么比如www.timinglee.org/a/s/d等都会自动跳转到https://www.timinglee.org
}
}
if ( !-e $request_filename ){
rewrite /(.*) https://$host/index.html redirect; ##对应上面,如果不存在,也自动跳转到https://www.timinglee.org
}
}
[root@nginx1 ~]# echo www.timinglee.org > /data/web/html/index.html
[root@nginx1 ~]# nginx -s reload
测试
6.6防盗链
防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标 记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗 链
正常访问
[root@nginx1 html]# cd /data/web/html/images/
[root@nginx1 images]# rz -E
rz waiting to receive.
[root@nginx1 images]# ls ##我们在/data/web/html/images/下放一张图片
1.jpg
6.6.1实现盗链
在一个web 站点盗链另一个站点的资源信息,比如:图片、视频等
示例
新开一台机子172.25.250.10,盗取另一台主机的www.timinglee.org/images/1.jpg的图片
[root@node1 ~]# yum install httpd -y
[root@node1 ~]# vim /var/www/html/index.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.timinglee.org/images/1.jpg" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.timinglee.org>狂点老李</a>出门见喜</p>
</body>
</html>
为了防止这种事情发生,就有防盗链
6.6.2防盗链
基于访问安全考虑,nginx支持通过ngx_http_referer_module模块,检查访问请求的referer信息是否有效 实现防盗链功能
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 /images {
valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;
if ( $invalid_referer ){
return 404;
}
}
}
上面可以看到还是看得见172.25.250.100主机里面的一些内容,所以我们要做全站防盗
全站
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 / { ##全站
valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;
if ( $invalid_referer ){
return 404;
}
}
}
为了更好玩一点,我们可以自定义让172.25.250.10主机看到我们想让其看到的内容
我们在172.25.250.100主机中的/data/web/html 下放上一张图片 名字为2.jpg
[root@nginx1 ~]# cd /data/web/html/
[root@nginx1 html]# rz -E
rz waiting to receive.
[root@nginx1 html]# ls ##我们在/data/web/html下放一张图片
2.jpg
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 /images {
valid_referers none blocked server_names *.timinglee.org ~/.baidu/.;
if ( $invalid_referer ){
rewrite ^/ http://www.timinglee.org/2.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案例:nginx反向代理及动静分离(实现http反向代理)
我们要额外添加两台机子,两台机子都安装好Apache
node1:172.25.250.10
node2:172.25.250.20
[root@nginx1 html]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
location / {
proxy_pass http://172.25.250.10:80;
}
location /static {
proxy_pass http://172.25.250.20:8080;
}
}
[root@nginx1 html]# nginx -s reload
##node1
[root@node1 ~]# echo 172.25.250.10 > /var/www/html/index.html
##node2
[root@node2 ~]# echo 172.25.250.20 > /var/www/html/index.html
[root@node2 ~]# vim /etc/httpd/conf/httpd.conf
##进入里面吧node2端口改为8080
##测试
[C:\~]$ curl www.timinglee.org
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14 100 14 0 0 1625 0 --:--:-- --:--:-- --:--:-- 2800
172.25.250.10
[C:\~]$ curl www.timinglee.org/static
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 196 100 196 0 0 11110 0 --:--:-- --:--:-- --:--:-- 14000
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
##因为172.25.250.20上没有static这个目录,所以需要创建
[root@node2 ~]# mkdir -p /var/www/html/static
[root@node2 ~]# echo static 172.35.250.20 > /var/www/html/static/index.html
[root@node2 ~]# systemctl restart httpd
##再次访问
[C:\~]$ curl www.timinglee.org/static/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 21 100 21 0 0 2166 0 --:--:-- --:--:-- --:--:-- 3500
static 172.35.250.20
动静分离
[root@nginx1 html]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
location ~ \.php$ {
proxy_pass http://172.25.250.10:80;
}
location /static {
proxy_pass http://172.25.250.20:8080;
}
}
[root@nginx1 html]# nginx -s reload
##node1
[root@node1 ~]# yum install php -y
[root@node1 ~]# systemctl restart httpd
[root@node1 ~]# vim /var/www/html/index.php
<?php
phpinfo();
?>
测试
php----动
static----静
7.2nginx反向代理缓存功能
[root@nginx1 html]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timinglee.org;
location ~ \.php$ {
proxy_pass http://172.25.250.10:80;
}
location /static {
proxy_pass http://172.25.250.20:8080;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
}
}
[root@nginx1 html]# nginx -s reload
[root@nginx1 html]# vim /usr/local/nginx/conf/nginx.conf
proxy_cache_path /usr/local/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
7.3http反向代理负载均衡
#自定义一组服务器,配置在http块内
upstream name {
server .....
......
}
#示例
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
server address [parameters];
#配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置。
#server支持的parameters如下:
weight=number #设置权重,默认为1,实现类似于LVS中的WRR,WLC等
max_conns=number #给当前后端server设置最大活动链接数,默认为0表示没有限制
max_fails=number #后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
fail_timeout=time #后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
backup #设置为备份服务器,当所有后端服务器不可用时,才会启用此备用服务器
down #标记为down状态,可以平滑下线后端服务器
resolve #当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginxhash KEY [consistent];
#基于指定请求报文中首部字段或者URI等key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是Cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算
hash $request_uri consistent; #基于用户请求的uri做hash
hash $cookie_sessionid #基于cookie中的sessionid这个key进行hash调度,实现会话绑定
ip_hash;
#源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持
least_conn;
#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的WLC
示例:后端多台 web服务器
node主机都下载Apache,部署后端Apache服务器
yum install httpd -y
##node1主机
[root@node1 ~]# echo "web1 172.25.250.10" > /var/www/html/index.html
[root@node1 ~]# systemctl enable --now httpd
##node2主机
[root@node2 ~]# echo "web2 172.25.250.20" > /var/www/html/index.html
[root@node2 ~]# systemctl enable --now httpd
##配置nginx反向代理
##注意:本节实验中先关闭缓存
[root@nginx1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
upstream webserver {
server 172.25.250.10:80 fail_timeout=15s max_fails=3;
server 172.25.250.20:80 fail_timeout=15s max_fails=3;
server 172.25.250.100 backup;
}
server {
listen 80;
server_name www.timinglee.org;
location / {
proxy_pass http://webserver;
}
}
[root@nginx1 ~]# nginx -s reload
##测试 ##默认为轮询
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
[C:\~]$ curl www.timinglee.org
web2 172.25.250.20
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
[C:\~]$ curl www.timinglee.org
web2 172.25.250.20
###对ip进行hash
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
upstream webserver {
ip_hash; #####hash运算,就是同一个ip来源的请求都转到同一台主机上
server 172.25.250.10:80 fail_timeout=15s max_fails=3;
server 172.25.250.20:80 fail_timeout=15s max_fails=3;
#server 172.25.250.100 backup; ##用hash不能用backup,防止调度到这上面来
}
server {
listen 80;
server_name www.timinglee.org;
location / {
proxy_pass http://webserver;
}
}
##测试
##真实主机
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
[C:\~]$ curl www.timinglee.org
web1 172.25.250.10
##node1主机和node2主机
##但是得先写解析,1主机和2主机一样
[root@node1 ~]# curl www.timinglee.org
web1 172.25.250.10
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.10 node1
172.25.250.100 www.timinglee.org
##node1主机
[root@node1 ~]# curl www.timinglee.org
web1 172.25.250.10
[root@node1 ~]# curl www.timinglee.org
web1 172.25.250.10
[root@node1 ~]# curl www.timinglee.org
web1 172.25.250.10
###node2主机
[root@node2 ~]# curl www.timinglee.org
web1 172.25.250.10
[root@node2 ~]# curl www.timinglee.org
web1 172.25.250.10
##对uri进行hash
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
upstream webserver {
#ip_hash;
hash $request_uri consistent;
server 172.25.250.10:80 fail_timeout=15s max_fails=3;
server 172.25.250.20:80 fail_timeout=15s max_fails=3;
#server 172.25.250.100 backup;
}
server {
listen 80;
server_name www.timinglee.org;
location / {
proxy_pass http://webserver;
}
}
[root@nginx1 ~]# nginx -s reload
##测试
[C:\~]$ curl www.timinglee.org
web2 172.25.250.20
[C:\~]$ curl www.timinglee.org
web2 172.25.250.20
[C:\~]$ curl www.timinglee.org
web2 172.25.250.20
#####访问不变,因为uri没变
###对cookie值进行hash运算
[root@nginx1 ~]# cat /usr/local/nginx/conf.d/vhost.conf
upstream webserver {
#ip_hash;
#hash $request_uri consistent;
hash cookie_ren; ###对cookie值进行hash
server 172.25.250.10:80 fail_timeout=15s max_fails=3;
server 172.25.250.20:80 fail_timeout=15s max_fails=3;
#server 172.25.250.100 backup;
}
server {
listen 80;
server_name www.timinglee.org;
location / {
proxy_pass http://webserver;
}
}
[root@nginx1 ~]# nginx -s reload
###测试
当访问 curl www.timiinglee.org时,它是轮询的
当curl -b "ren=1" www.timinglee.org时,只访问web1 172.25.250.10
当curl -b "ren=2" www.timinglee.org时,只访问web2 172.25.250.20
7.4实现nginx四层负载均衡(tcp)
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;
}
}
7.4.1 负载均衡示例:基于dns负载均衡
##node1和node2配置dns
##node2配置dns
yum install bind -y
vim /etc/named
[root@node2 ~]# vim /etc/named.rfc1912.zones
[root@node2 ~]# cd /var/named/
[root@node2 named]# cp named.localhost timinglee.org.zone -p
[root@node2 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.250.20
www A 172.25.250.20
[root@node2 named]# systemctl restart named
[root@node2 named]# dig www.timinglee.org @172.25.250.20
###將node2主机的配置复制到node1主机的/etc下面
[root@node2 named]# scp -p /etc/named.{conf,rfc1912.zones} root@172.25.250.10:/etc/
[root@node2 named]# scp -p /var/named/timinglee.org.zone root@172.25.250.10:/var/named/timinglee.org.zone
##node1主机
[root@node1 ~]# ll /etc/named.conf
-rw-r-----. 1 root named 1727 Aug 19 19:44 /etc/named.conf
[root@node1 ~]# ll /etc/named.rfc1912.zones
-rw-r-----. 1 root named 1148 Aug 19 19:46 /etc/named.rfc1912.zones
[root@node1 ~]# vim /var/named/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.250.10
www A 172.25.250.10
[root@node1 ~]# cd /var/named/
[root@node1 named]# ll
total 20
drwxrwx---. 2 named named 23 Aug 19 19:54 data
drwxrwx---. 2 named named 60 Aug 19 19:55 dynamic
-rw-r-----. 1 root named 2112 Feb 13 2024 named.ca
-rw-r-----. 1 root named 152 Feb 13 2024 named.empty
-rw-r-----. 1 root named 152 Feb 13 2024 named.localhost
-rw-r-----. 1 root named 168 Feb 13 2024 named.loopback
drwxrwx---. 2 named named 6 Feb 13 2024 slaves
-rw-r----- 1 root root 205 Aug 19 19:54 timinglee.org.zone
[root@node1 named]# chgrp named timinglee.org.zone
[root@node1 named]# ll
total 20
drwxrwx---. 2 named named 23 Aug 19 19:54 data
drwxrwx---. 2 named named 60 Aug 19 19:55 dynamic
-rw-r-----. 1 root named 2112 Feb 13 2024 named.ca
-rw-r-----. 1 root named 152 Feb 13 2024 named.empty
-rw-r-----. 1 root named 152 Feb 13 2024 named.localhost
-rw-r-----. 1 root named 168 Feb 13 2024 named.loopback
drwxrwx---. 2 named named 6 Feb 13 2024 slaves
-rw-r----- 1 root named 205 Aug 19 19:54 timinglee.org.zone
[root@node1 named]# systemctl restart named
[root@node1 named]# dig www.timinglee.org @172.25.250.10
然后我们在nginx1主机上
[root@nginx1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx1 ~]# mkdir -p /usr/local/nginx/tcpconf.d
[root@nginx1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf
stream {
upstream dns {
server 172.25.250.10:53 fail_timeout=15s max_fails=3;
server 172.25.250.20:53 fail_timeout=15s max_fails=3;
}
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
[root@nginx1 ~]# nginx -s reload
[root@nginx1 ~]# dig www.timinglee.org @172.25.250.100
###轮询来解析
测试
7.4.2 基于数据库负载均衡
###node1和node2主机都下载mariadb数据库
##node1
[root@node1 ~]#yum install mariadb-server -y
[root@node1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@node1 ~]# systemctl restart mariadb.service
[root@node1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[root@node2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
##node1
[root@node1 ~]# 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 ren@'%' identified by 'ren';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> grant all on *.* to ren@'%';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> quit
Bye
##node2
[root@node2 ~]# 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 ren@'%' identified by 'ren';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> grant all on *.* to ren@'%';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> quit
Bye
##nginx主机上
[root@nginx1 tcpconf.d]# vim /usr/local/nginx/tcpconf.d/dns.conf
stream {
upstream dns {
server 172.25.250.10:53 fail_timeout=15s max_fails=3;
server 172.25.250.20:53 fail_timeout=15s max_fails=3;
}
upstream mysql {
server 172.25.250.10:3306 fail_timeout=15s max_fails=3;
server 172.25.250.20:3306 fail_timeout=15s max_fails=3;
}
server {
listen 3306;
proxy_timeout 20s;
proxy_pass mysql;
}
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
yum install mariadb -y ##不是下载mariadb-server
##测试
[root@nginx1 tcpconf.d]# mysql -u ren -p -h 172.25.250.100
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 5
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)]> select @@server_id
-> ;
+-------------+
| @@server_id |
+-------------+
| 10 |
+-------------+
1 row in set (0.001 sec)
MariaDB [(none)]> quit
Bye
[root@nginx1 tcpconf.d]# mysql -u ren -pren -h 172.25.250.100
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 4
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)]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
1 row in set (0.001 sec)
MariaDB [(none)]> quit
Bye
[root@nginx1 tcpconf.d]# mysql -u ren -pren -h 172.25.250.100
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 6
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)]> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 10 |
+-------------+
1 row in set (0.001 sec)
MariaDB [(none)]> quit
Bye
测试
8.实现FastCGI
FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处 理,其配置指令如下
fastcgi_pass address:port; #转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in
location
fastcgi_index name;
#fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义
key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
Nginx默认配置示例:
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为
prefix/conf
}
8.1 nginx-源码编译php
[root@Nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
[root@nginx2 ~]# ls
anaconda-ks.cfg nginx-1.26.1 php-8.3.9.tar.gz
memc-nginx-module-0.20 nginx-1.26.1.tar.gz srcache-nginx-module-0.33
memc-nginx-module-0.20.tar.gz php-8.3.9 srcache-nginx-module-0.33.tar.gz
##将上面的压缩包都解压,解压的步骤我省略掉了,然后解压出来就是上面的样子
#利用yum解决php依赖
[root@nginx2 ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel oniguruma-devel
[root@nginx2 ~]# wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
#解压源码并安装
[root@nginx2 php-8.3.9 ]# ./configure \
--prefix=/usr/local/php \ #安装路径
--with-config-file-path=/usr/local/php/etc \ #指定配置路径
--enable-fpm \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cgi
##################
./configure --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
#########################
[root@Nginx ~]# make && make install
nginx的源码编译,编译完后make && make install
8.2php的配置优化
[root@nginx2 etc]# cd /usr/local/php/etc/
[root@nginx2 etc]# cp -p php-fpm.conf.default php-fpm.conf
[root@nginx2 etc]# ls
php-fpm.conf.default php-fpm.d
[root@nginx2 etc]# vim php-fpm.conf
[root@nginx2 etc]# cd php-fpm.d/
[root@nginx2 php-fpm.d]# ls
www.conf.default
[root@nginx2 php-fpm.d]# cp www.conf.default www.conf
[root@nginx2 php-fpm.d]# ls
www.conf www.conf.default
[root@nginx2 php-fpm.d]# cd /root/php-8.3.9/
[root@nginx2 php-8.3.9]# ls
appveyor CONTRIBUTING.md Makefile.objects SECURITY.md
benchmark docs modules tests
build ext NEWS travis
buildconf EXTENSIONS pear TSRM
buildconf.bat include php.ini-development UPGRADING
CODING_STANDARDS.md libs php.ini-production UPGRADING.INTERNALS
config.log libtool README.md win32
config.nice LICENSE README.REDIST.BINS Zend
config.status main run-tests.php
configure Makefile sapi
configure.ac Makefile.fragments scripts
[root@nginx2 php-8.3.9]# cd /root/php-8.3.9/
[root@nginx2 php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@nginx2 php-8.3.9]# cd /usr/local/php/etc
[root@nginx2 etc]# ls
php-fpm.conf php-fpm.conf.default php-fpm.d php.ini
[root@nginx2 etc]# vim php.ini
[root@nginx2 etc]# cd /root/php-8.3.9/
[root@nginx2 php-8.3.9]# ls
appveyor CONTRIBUTING.md Makefile.objects SECURITY.md
benchmark docs modules tests
build ext NEWS travis
buildconf EXTENSIONS pear TSRM
buildconf.bat include php.ini-development UPGRADING
CODING_STANDARDS.md libs php.ini-production UPGRADING.INTERNALS
config.log libtool README.md win32
config.nice LICENSE README.REDIST.BINS Zend
config.status main run-tests.php
configure Makefile sapi
configure.ac Makefile.fragments scripts
[root@nginx2 php-8.3.9]# cd sapi/
[root@nginx2 sapi]# ls
apache2handler cgi cli embed fpm fuzzer litespeed phpdbg
[root@nginx2 sapi]# cd fpm/
[root@nginx2 fpm]# ls
config.m4 init.d.php-fpm.in php-fpm.8 php-fpm.service tests
CREDITS LICENSE php-fpm.8.in php-fpm.service.in www.conf
fpm Makefile.frag php-fpm.conf status.html www.conf.in
init.d.php-fpm php-fpm php-fpm.conf.in status.html.in
[root@nginx2 fpm]# cp php-fpm.service /lib/systemd/system/
[root@nginx2 fpm]# pwd
/root/php-8.3.9/sapi/fpm
[root@nginx2 fpm]# vim /lib/systemd/system/php-fpm.service
[root@nginx2 fpm]# systemctl daemon-reload
[root@nginx2 fpm]# systemctl start php-fpm.service
[root@nginx2 fpm]# netstat -antlupe | grep php
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 0 32174 2087/php-fpm: maste
[root@nginx2 php]# cd /usr/local/nginx/conf
[root@nginx2 conf]# ls
fastcgi.conf koi-utf nginx.conf uwsgi_params
fastcgi.conf.default koi-win nginx.conf.default uwsgi_params.default
fastcgi_params mime.types scgi_params win-utf
fastcgi_params.default mime.types.default scgi_params.default
[root@nginx2 conf]# cd ..
[root@nginx2 nginx]# ls
client_body_temp conf.d html proxy_temp scgi_temp
conf fastcgi_temp logs sbin uwsgi_temp
[root@nginx2 nginx]# vim conf.d/
[root@nginx2 nginx]# vim conf.d/nginx.conf
[root@nginx2 nginx]# vim conf/nginx.conf
[root@nginx2 nginx]#
8.3准备php测试页面
mkdie -p /data/web/php
vim /data/web/php/index.php
<?php
phpinfo();
?>
mkdir -p /usr/local/nginx/conf.d
vim /usr/local/nginx/conf.d/php.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 -s reload
这里注意要做好Windows下的本地解析
比如我目前主机为172.25.250.200,那么要在浏览器中访问就要在Windows下的
8.4添加php环境变量
[root@nginx2 ~]# vim .bash_profile
[root@nginx2 ~]# cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
export PATH=$PATH:/usr/local/nginx/sbin
PATH=$PATH:$HOME/bin:/apps/nginx/sbin:/usr/local/php/bin ##添加这一行
[root@nginx2 ~]# source .bash_profile
8.5php缓存优化
[root@nginx2 ~]# yum install httpd-tools
[root@nginx2 ~]# ab -n1000 -c10 http://www.timinglee.org/index.php
[root@nginx2 ~]# php -m | grep mem ##暂时不支持,需要第三方软件包
[root@nginx2 ~]# ls
anaconda-ks.cfg nginx-1.26.1 srcache-nginx-module-0.33
memcache-8.2.tgz nginx-1.26.1.tar.gz srcache-nginx-module-0.33.tar.gz
memc-nginx-module-0.20 php-8.3.9
memc-nginx-module-0.20.tar.gz php-8.3.9.tar.gz
[root@nginx2 ~]# tar xzf memcache-8.2.tgz ##解压 memcache-8.2.tgz
[root@nginx2 ~]# cd memcache-8.2/
[root@nginx2 memcache-8.2]# ls
config9.m4 config.w32 docker example.php memcache.php src
config.m4 CREDITS Dockerfile LICENSE README tests
[root@nginx2 memcache-8.2]# yum install autoconf -y
[root@nginx2 memcache-8.2]# ./configure && make && make install
[root@nginx2 memcache-8.2]# ls
autom4te.cache config.log configure.ac example.php Makefile.fragments README
build config.m4 config.w32 include Makefile.objects run-tests.php
config9.m4 config.nice CREDITS libtool memcache.la src
config.h config.status docker LICENSE memcache.php tests
config.h.in configure Dockerfile Makefile modules
[root@nginx2 memcache-8.2]# cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
[root@nginx2 no-debug-non-zts-20230831]# ls
memcache.so opcache.so
[root@nginx2 no-debug-non-zts-20230831]# cd
[root@nginx2 ~]# cd /usr/local/php/etc/
[root@nginx2 etc]# vim php.ini
[root@nginx2 etc]# vim php.ini
[root@nginx2 etc]# systemctl restart php-fpm.service
[root@nginx2 etc]# php -m | grep mem ##支持了
memcache ##已经有了这个参数
vim /usr/local/php/etc/php.ini
[root@nginx2 etc]# yum install memcached -y
[root@nginx2 etc]# systemctl start memcached.service
[root@nginx2 etc]# cd
[root@nginx2 ~]# cd memcache-8.2/
[root@nginx2 memcache-8.2]# ls
autom4te.cache config.log configure.ac example.php Makefile.fragments README
build config.m4 config.w32 include Makefile.objects run-tests.php
config9.m4 config.nice CREDITS libtool memcache.la src
config.h config.status docker LICENSE memcache.php tests
config.h.in configure Dockerfile Makefile modules
[root@nginx2 memcache-8.2]# cp example.php memcache.php /data/web/php/
[root@nginx2 memcache-8.2]# cd /data/web/php/
[root@nginx2 php]# ls
example.php html index.php memcache.php
[root@nginx2 php]# vim memcache.php
[root@nginx2 php]# systemctl restart php-fpm.service
vim /data/web/php/memcache.php
测试
8.6php高速缓存
在我们安装的nginx中默认不支持memc和srcache功能,需要借助第三方模块来让nginx支持此功能,所 以nginx需要重新编译
[root@nginx2 ~]# tar zxf srcache-nginx-module-0.33.tar.gz
[root@nginx2 ~]# tar zxf memc-nginx-module-0.20.tar.gz
[root@nginx2 ~]# cd nginx-1.26.1/
[root@nginx2 nginx-1.26.1]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/root/memc-nginx-module-0.20 --add-module=/root/srcache-nginx-module-0.33
[root@nginx2 nginx-1.26.1]# make && make install
[root@nginx2 nginx-1.26.1]# cd /usr/local/nginx/conf.d/
[root@nginx2 conf.d]# ls
php.conf
[root@nginx2 conf.d]# vim php.conf
upstream memcache {
server 172.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
location /memc {
internal;
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
mems_read_timeout 100ms;
set $mem_key $query_string;
set $memc_exptime 300;
memc_pass memcache;
}
location ~ \.php$ {
root /data/web/php;
set $key $uri$args;
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
[root@nginx2 conf.d]# nginx -s reload
[root@nginx2 conf.d]# ab -n500 -c10 http://www.timinglee.org/index.php