一、web基础介绍
Apache 和 Nginx 是当今为互联网提供动力的最流行的Web 服务器。
1.1、apache服务器
1.1.1、Apache prefork 模型
- 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
- 每个子进程有一个独立的线程响应用户请求
- 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
- 是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.1.2、Apache worker 模型
- 一种多进程和多线程混合的模型
- 有一个控制进程,启动多个子进程 每个子进程里面包含固定的线程
- 使用线程程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求
- 由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
1.1.3、Apache event模型
- Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型
- (epoll) 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
- 它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
- event MPM中,会有一个专门的线程来管理这些keepalive类型的线程。当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
1.2、Nginx高性能服务器
Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发 工作最早从2002年开始,第一次公开发布时间是2004年10月4日,版本号是0.1.0
Nginx的版本分为开发版、稳定版和过期版,nginx以功能丰富著称,它即可以作为http服务 器,也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求
支持FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以 上且开启stream模块)等功能,并且支持第三方的功能扩展。
天猫 淘宝 京东 小米 163 新浪等一线互联网公司都在用Nginx或者进行二次开发
官网地址 www.nginx.org
工作场景:
1.3、服务端 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:
1、磁盘I/O
2、网络I/O : 一切皆文件,本质为对socket文件的读写
1.3.1、磁盘I/O
磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相 应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存, 如果是比较大的数据也需要等待时间。
1.3.2、网络I/O
网络通信就是网络协议栈到用户空间进程的IO就是网络IO
- 1-3:网络I/O 处理过程 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求
- 4:构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成
- 5-7:返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端
不论磁盘和网络I/O 每次I/O,都要经由两个阶段:
第一步:将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
1.3.3、I/O 模型
1、同步/异步
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事 情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
2、阻塞/非阻塞
apache:典型的同步阻塞
1.3.3.1 阻塞型 I/O 模型(blocking IO)
一个只能执行一个请求
1.3.3.2 非阻塞型 I/O 模型 (nonblocking IO)
1.3.3.3 多路复用 I/O 型(I/O multiplexing)
1.3.3.4 信号驱动式 I/O 模型 (signal-driven IO)
1.3.3.5 异步 I/O 模型 (asynchronous IO)
1.3.3.6、五种I/O对比
1.4、I/O常见实现方式
1、select: select库是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
2、poll: 在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
3、epoll: epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和 select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.epoll的处理方式是创建一个 待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮询检查这个表,以判断事件是否发 生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的 I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。
1.4.1、常用I/O方式比较
1.5、零拷贝
零拷贝就是I/O问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做 到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化
1.5.1、 传统 Linux中 I/O 的问题
传统的 Linux 系统的标准 I/O 接口(read、write)是基于数据拷贝的,也就是数据都是 copy_to_user 或者 copy_from_user,这样做的好处是,通过中间缓存的机制,减少磁盘 I/O 的操作,但是坏处也很明 显,大量数据的拷贝,用户态和内核态的频繁切换,会消耗大量的 CPU 资源,严重影响数据传输的性能。
1.5.2、零拷页相关技术
1.5.2.1、MMAP ( Memory Mapping )
1.5.2.2、SENDFILE
1.5.2.3、DMA辅助的SENDFLIE(需要硬件,使用的较少)
二、Nginx 架构和安装
2.1、Nginx 功能介绍
- 静态的web资源服务器html,图片,js,css,txt等静态资源
- http/https协议的反向代理
- 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
- tcp/udp协议的请求转发(反向代理)
- imap4/pop3协议的反向代理
2.2、基础特性
- 模块化设计,较好的扩展性
- 高可靠性
- 支持热部署:不停机更新配置文件,升级版本,更换日志文件
- 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
- event-driven,aio,mmap,sendfile
2.3、Nginx 进程结构
2.3.1、Nginx 进程间通信
2.3.2、 Nginx 模块介绍
nginx 有多种模块:
- 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件 驱动机制 、进程管理等核心功能
- 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应 头设置 等等
- 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
- 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的 支持
- Stream服务模块: 实现反向代理功能,包括TCP协议代理
- 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支 持等
2.4、Nginx 安装
2.4.1、Nginx版本和安装方式
官方源码包下载地址:https://nginx.org/en/download.html
我用的是1.24和1.26的
Nginx版本
Nginx安装可以使用yum或源码安装,但是推荐使用源码编译安装
- yum的版本比较旧
- 编译安装可以更方便自定义相关路径
- 使用源码编译可以自定义相关功能,更方便业务的上的使用
2.4.2.Nginx 编译安装
2.4.2.1、编译安装nginx
源码安装需要提前准备标准的编译器
GCC可以处理C++,Fortran,pascal,objective C, java以及Ada等其他语言,此外还需要Automake工具,以完成自动创建Makefile的工作,Nginx的一些模块 需要依赖第三方库,比如: pcre(支持rewrite),zlib(支持gzip模块)和openssl(支持ssl模块)
[root@Nginx ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
上传nginx安装包,解压
解压后,进入源码目录
[root@nginx ~]# cd nginx-1.24.0/
[root@nginx ~]# useradd -s /sbin/nologin -M nginx
开始编译,执行./configure
注:nginx使用yum源安装,可能导致业务上很多需要的功能模块没有开启,还是按需自己编译比较合适。
[root@nginx nginx-1.24.0]# ./configure --help
#查看./configure 支持哪些参数
[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \ #指定安装路径
--user=nginx \ # 指定nginx运行用户
--group=nginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip
[root@Nginx nginx-1.24.0]# make #没有报错代表执行成功
注:make执行完成后生成的中间件文件,都会放在(/root/nginx-1.24.0/objs/src/)目录下面
[root@Nginx nginx-1.24.0]# make install #执行安装命令,第一次安装可以执行,如果是升级,就不能执行install命令。
注:这个命令是把objs目录下生成nginx二进制文件拷贝到原老版本的nginx目录下。
安装完成后,安装目录为/usr/local/nginx/
[root@Nginx nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin
conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他 的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params 两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀 去掉即可。
html:保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web 文件是默认的错误页面提示页面。
logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比 如/var/logs/nginx里面。
sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
2.4.2.2、验证版本及编译参数
为了方便使用Nginx命令,需要将Nginx的可执行文件路径添加到系统的环境变量中。
[root@nginx nginx-1.24.0]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
执行以下命令使环境变量生效
[root@nginx nginx-1.24.0]# source ~/.bash_profile
为了验证Nginx是否成功安装并正常运行,可以使用以下命令启动Nginx服务
2.4.2.3、使用安装完成的二进制文件nginx
[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 #设置全局指令,注意和 配置文件不要同时配置,否则冲突
2.5、平滑升级和回滚
2.5.1、平滑升级
上传另一个版本的nginx安装包,解压并进入源码目录
[root@nginx ~]# tar zxf nginx-1.26.1.tar.gz
[root@nginx ~]# cd nginx-1.26.1/
下一步也是开始编译,执行./configure[root@Nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \ #指定安装路径
--user=nginx \ # 指定nginx运行用户
--group=nginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip
此时就只需make,无需make install
[root@nginx nginx-1.26.1]# make
安装完成后,开始准备升级。
#把之前的旧版的nginx命令备份
[root@nginx ~]# cd /usr/local/nginx/sbin/
[root@nginx sbin]# cp nginx nginx.24
#把新版本的nginx命令复制过去
[root@nginx sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/
[root@nginx sbin]# ls
nginx nginx.24#检测一下有没有问题
#查看一下现在的进程
[root@nginx sbin]# kill -USR2 48217
- #USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的 nginx
- #此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
- #此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进 程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理。
此时任然是旧版本生效
#检测版本信息
#回收旧版本
[root@nginx nginx-1.24.0]# kill -WINCH 48217
#再次检测版本信息
2.5.2、回滚
#如果升级的版本发现问题需要回滚,可以重新拉起旧版本的worker
#将现在的nginx命令备份
[root@nginx sbin]# cp nginx nginx.26
[root@nginx sbin]# ls
nginx nginx.26 nginx.24[root@nginx sbin]# mv nginx.old nginx
mv: overwrite 'nginx'? y
[root@nginx sbin]# ls
nginx nginx.26现在就已经将nginx改为以前的版本了
后就拉起旧版本的worker
[root@nginx nginx-1.24.0]# kill -HUP 48217
现在回收新版本
再检测版本信息
这样就回滚完成了
三 Nginx 核心配置详解
3.1 配置文件说明
nginx 官方帮助文档:http://nginx.org/en/docs/
Nginx的配置文件的组成部分:
- 主配置文件:、/usr/local/nginx/conf/nginx.conf
- 子配置文件: include conf.d/*.conf fastcgi, uwsgi,scgi 等协议相关的配置文件
- mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮 件扩展类型
nginx 配置文件格式说明:
- 配置文件由指令与指令块构成
- 每条指令以;分号结尾,指令与值之间以空格符号分隔
- 可以将多条指令放在同一行,用分号分隔即可,但可读性差,不推荐
- 指令块以{ }大括号将多条指令组织在一起,且可以嵌套指令块
- include语句允许组合多个配置文件以提升可维护性
- 使用#符号添加注释,提高可读性
- 使用$符号使用变量
- 部分指令的参数支持正则表达式
主配置文件 结构:(四部分)
main block:主配置段,即全局配置段,对http,mail都有效
1、事件驱动相关的配置(event)
2、http/https 协议相关配置段(HTTP)
#默认配置文件不包括下面两个块
3、协议相关配置段(mail)
4、服务器相关配置段(stream)
3.2 全局配置
Main 全局配置段常见的配置指令分类
- 正常运行必备的配置
- 优化性能相关的配置
- 用于调试及定位问题相关的配置
- 事件驱动相关的配置
全局配置说明:
#全局配置端,对全局生效,主要设置nginx的启动用户/组,启动的工作进程数量,工作模式,Nginx的PID路径,日志路径等。
user nginx nginx; #启动Nginx工作进程的用户和组
worker_processes [number | auto]; #启动Nginx工作进程的数量,一般设为和CPU核心数相同
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ;
- 将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的
- 绑定并不是意味着当前nginx进程独占以一核心CPU,但是可以保证此进程不运行在其他核心上,
- 这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转
- 减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务 器的性能。
#错误日志记录配置,语法:
error_log file [debug | info | notice | warn | error | crit | alert | emerg]
#其中debug级别的日志需要编译时使用--with-debug开启debug开关
pid #文件保存路径
pid /usr/local/nginx/logs/nginx.pid;
worker_priority 0; #工作进程优先级,-20~20(19)
worker_rlimit_nofile 65536; #所有worker进程能打开的文件数量上限,
#包括:Nginx的所有连接(例如与代理服务器的连接等)
#而不仅仅是与客户端的连接
#另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件 数的限制
#最好与ulimit -n 或者limits.conf的值保持一致,
daemon off; #前台运行Nginx服务用于测试、docker等环境。
master_process off|on; #是否开启Nginx的master-worker工作模式,仅用于开发调试场景,默认为 on
示例1 、设置nginx的启动用户/组,启动的工作进程数量
因为我这个虚拟的处理器内核有两个,auto(自动)就为2
2核cpu,开启2个进程
解释:01表示启用第一个CPU内核,10表示启用第二个CPU内核
worker_cpu_affinity 01 10;表示开启两个进程,第一个进程对应着第一个CPU内核,第二个进程对应着第二个CPU内核。
示例2、Nginx的PID路径,日志路径
3.3、event配置块
events {
worker_connections 65535; #设置单个工作进程的最大并发连接数
use epoll; #使用epoll事件驱动,
#Nginx支持众多的事件驱动,
#比如:select、poll、epoll,只能设置在events模块中设置
accept_mutex on; #on为同一时刻一个请求轮流由work进程处理,
#而防止被同时唤醒所有worker
#避免多个睡眠进程被唤醒的设置,默认为off
#新请求会唤醒所有worker进程,此过程也称为"惊群"
#因此nginx刚安装完以后要进行适当的优化。建议设置为on
multi_accept on; #on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接
#此指令默认为off,
#即默认为一个工作进程只能一次接受一个新的网络连接
#打开后几个同接受多个。建议设置为on
}
示例、实现 nginx 的高并发配置
#修改pam限制
[root@nginx ~]# sudo -u nginx ulimit -n
1024
[root@nginx ~]# vim /etc/security/limits.confnginx - nofile 100000
[root@nginx ~]# sudo -u nginx ulimit -n
100000单个处理器的最大并发连接数
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx ~]# nginx -s reload
压力测试
[root@nginx ~]# yum install httpd-tools -y
3.4 http 配置块
http{
#在响应报文中将指定的文件扩展名映射至MIME对应的类型
include /etc/nginx/mime.types;
default_type application/octet-stream; #除mime.types中的类型外
#指定其它文件的默认MIME类型,浏览 器一般会提示下载
types {
text/html html;
image/gif gif;
image/jpeg jpg;
}
}
3.5、核心配置示例
#注意在访问主机中设解析
3.5.1、新建一个 PC web 站点
[root@nginx ~]# mkdir -p /usr/local/nginx/conf.d
#创建虚拟主机网站配置
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx ~]# mkdir -p /data/web/html
[root@nginx ~]# echo www.timingzpy.org > /data/web/html/index.html
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
localtion /test1/ {
root /data/web;
}
}
3.4.2、root 与 alias
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制;仅能用于 location上下文,此指令使用较少
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
location /test1/ {
root /data/web;
}
location /test2 {
alias /data/web/test1;
}
}
[root@nginx ~]# nginx -s reload
3.5.3、location 的详细使用
- 在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;
- ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,
- 而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最 高的一个uri
- uri是用户请求的字符串,即域名后面的web文件路径
- 然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理 此请求。
#语法规则: location [ = | ~ | ~* | ^~ ] uri { ... }
= #需要请求字串与uri精确匹配,如果匹配成功就停止向下匹配并立 即处理请求
^~ #表示包含正则表达式,并且匹配以指定的正则表达式开头
#对uri的最左边部分做匹配检查,不区分字符大小写
~ #表示包含正则表达式,并且区分大小写
~* #表示包含正则表达式,并且不区分大写
不带符号 #匹配起始于此uri的所有的uri
\ #表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号
1、精确匹配
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
location = /index.html {
root /data/web1/test;
}
}
[root@nginx ~]# mkdir /data/web1/test -p
[root@nginx ~]# echo web1 > /data/web1/test/index.html
[root@nginx ~]# nginx -s reload
2、访问目录优先级
访问目录优先级从高到低:~ /~*(他们两个优先级一样,谁在前面谁先执行),不带符号,^~
=:不能直接匹配目录,
[root@nginx data]# ls
web web1 web2[root@nginx data]# mkdir -p /data/web{3..5}
[root@nginx data]# mkdir -p /data/web{3..5}/test
[root@nginx data]# echo web3 > /data/web3/test/index.html
[root@nginx data]# echo web4 > /data/web4/test/index.html
[root@nginx data]# echo web5 > /data/web5/test/index.html[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;location /test {
root /data/web2;
}location ^~ /t {
root /data/web3;
}location ~ .html$ {
root /data/web4;
}location ~* .HTML$ {
root /data/web5;
}}
3、访问文件优先级从高到低:=,~ /~*(他们两个谁优先级在前面谁优先级高),不带符号,^~
location = /index.html {
root /data/web1/test;
}location /index.html {
root /data/web2/test;
}location ^~ /i {
root /data/web3/test;
}location ~ /index.html {
root /data/web4,test;
}location ~* /index.html {
root /data/web5/test;
}
3.5.4、Nginx 账户认证功能
建立用户认证
[root@nginx ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$ViXY3Jof$aOdIwsAzau.qHCZOT4iwa/
[root@nginx ~]# htpasswd -m /usr/local/nginx/.htpasswd zpy
New password:
Re-type new password:
Adding password for user zpy
[root@nginx ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$ViXY3Jof$aOdIwsAzau.qHCZOT4iwa/
zpy:$apr1$w2n.qOxa$c5YTtyLQWvjXhRUVCSVpZ0
[root@nginx ~]# mkdir /data/web/zpy
[root@nginx ~]# echo zpy > /data/web/zpy/index.html[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;location /zpy {
root /data/web;
auth_basic "login password !!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
}
#重启Nginx并访问测试
3.5.5、自定义错误页面
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
[root@nginx ~]# nginx -s reload
[root@nginx ~]# cat /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;location = /40x.html {
root /data/web/errorpage;
}
}[root@nginx ~]# mkdir /data/web/zpy
[root@nginx ~]# echo zpy > /data/web/zpy/index.html
[root@nginx ~]# mkdir -p /data/web/errorpage
[root@nginx ~]# echo error page > /data/web/errorpage/40x.html
#重启nginx并访问不存在的页面进行测试
3.5.6、自定义错误日志
[root@nginx ~]# mkdir -p /var/log/timingzpy.org
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
error_log /var/log/timingzpy.org/error.log;
access_log /var/log/timingzpy.org/access.log;}
[root@nginx ~]# nginx -s reload
测试:
自动生成两个文件
3.5.7、检测文件是否存在
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
try_files $uri $uri.html $uri/index.html /error/default.html;
}
[root@nginx ~]# mkdir /data/web/html/error
[root@nginx ~]# echo error default > /data/web/html/error/default.html[root@nginx ~]# nginx -s reload
测试:
该文件不存在
3.5.8、长连接配置
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
http {
…………
keepalive_timeout 65; #这个链接在未请求的时候保持65s后断开
keepalive_request 2; #该链接允许请求访问两次
…………}
长链接测试工具
yum install telnet -y
测试:
输入
GET / HTTP/1.1
Host: www.timingzpy.org
回车两次,一次构建报文建立连接,二次发送
只允许我访问两次,就直接关闭了
keepalive_timeout 65 60; #这个链接在未请求的时候保持65s后断开,但只让用户看到为60s
3.5.9、作为下载服务器配置
#注意:download不需要index.html文件
[root@nginx ~]# mkdir /data/web/download
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
location /download {
root /data/web;
autoindex on; #自动索引功能
autoindex_localtime on; #on表示显示本机时间而非GMT(格林威治)时间#默认为off显 示GMT时间
autoindex_exact_size off; #计算文件确切大小(单位bytes)#此为默认值,off只显示 大概大小(单位kb、mb、gb)
limit_rate 1024k; #限速,默认不限速(为0)
}
[root@nginx ~]# nginx -s reload
测试:
四、Nginx 高级配置
4.1、Nginx 状态页
注意: 状态页显示的是整个服务器的状态,而非虚拟主机的状态
[root@nginx conf.d]# vim status.conf
[root@nginx conf.d]# pwd
/usr/local/nginx/conf.dserver {
listen 80;
server_name status.timingzpy.org;
root /data/web/html;
index index.html;location /status {
stub_status;
#auth_basic "login"; 允许账号登录
#auth_basic_user_file "usr/local/nginx/.htpasswd"; #前文Nginx 账户认证功能中的账号
allow 172.25.254.1; #只允许本地登录
deny all; #禁止其他登录
}
}
[root@nginx conf.d]# nginx -s reload
测试:
本地登录
4.2、Nginx 压缩功能
我们最开始下载的zlib-devel,就是来使用压缩功能的
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
http {
…………
#启用或禁用gzip压缩,默认关闭
gzip on;#压缩比由低到高从1到9,默认为1,值越高压缩后文件越小,但是消耗cpu比较高。
#基本设定为4或者5
gzip_comp_level 5;#gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;#启用压缩功能时,协议的最小版本,默认HTTP/1.1
gzip_http_version 1.1;#如果启用压缩,是否在响应报文首部插入“Vary: Accept-Encoding”,一般建议打开
gzip_vary on;#指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
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 ~]# nginx -s reload
测试:
[root@nginx conf.d]# echo hello timingzpy > /data/web/html/small.html
[root@nginx conf.d]# du -sh /usr/local/nginx/logs/access.log
17M /usr/local/nginx/logs/access.log
[root@nginx conf.d]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html
4.3、Nginx的版本隐藏
4.4、Nginx 变量使用
- nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用
- 变量可以分为内置变量和自定义变量
- 内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。
4.4.1、内置变量
官方文档:http://nginx.org/en/docs/varindex.html
[root@nginx conf.d]# pwd
/usr/local/nginx/conf.d[root@nginx conf.d]# vim vars.conf
server {
listen 80;
server_name var.timingzpy.org;
root /data/web/html;
index index.html;location /var {
default_type text/html;
echo $remote_addr; #存放了客户端的地址,注意是客户端的公网IP
echo $args; #变量中存放了URL中的所有参数
echo $is_args; #如果有参数为? 否则为空
echo $document_root; #保存了针对当前资源的请求的系统根目录
echo $document_uri; #保存了当前请求中不包含参数的URI,注意是不包含请求的指令
echo $host; #存放了请求的host名称
echo $remote_port; #客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口
echo $remote_user; #已经经过Auth Basic Module验证的用户名
echo $request_method; #请求资源的方式,GET/PUT/DELETE等
echo $request_filename; #当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径
echo $request_uri; #包含请求参数的原始URI,不包含主机名
echo $scheme; #请求的协议
echo $server_protocol; #保存了客户端请求资源使用的协议的版本
echo $server_addr; #保存了服务器的IP地址
echo $server_name; #虚拟主机的主机名
echo $server_port; #虚拟主机的端口号
echo $http_user_agent; #客户端浏览器的详细信息
echo $http_cookie; #客户端的所有cookie信息
echo $cookie_key2; #name为任意请求报文首部字部cookie的key名
}
}[root@nginx conf.d]# nginx -s reload(每次写完子配置文件都要记得reload哦!)
测试:
[root@nginx conf]# curl -b "key1=zpy,key2=zpy1" -u zpy:zpy var.timingzpy.org/v=lee&&id=6666
172.25.254.100
name=zpy
?
/data/web/html
/var
var.timingzpy.org
45924
lee
GET
/data/web/html/var
/var?name=zpy
http
HTTP/1.1
172.25.254.100
var.timingzpy.org
80
curl/7.76.1
key1=zpy,key2=zpy1
zpy1
4.4.2、自定义变量
使用指令set $variable value;
server {
listen 80;
server_name var.timingzpy.org;
root /data/web/html;
index index.html;location /var {
default_type text/html;
set $timingzpy zpy;
echo $timingzpy;
}
}
测试:
五、Nginx Rewrite 相关功能
- Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
- 此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
- rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
- 比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
- 另外还可以在一定程度上提高网站的安全性。
5.1、ngx_http_rewrite_module 模块指令
官方文档:http:// https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
5.1.1、if指令
- Nginx的if语法仅能使用if做单次判断
- 可以使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false
location /test2 {
if ( !-e $request_filename ){
echo "$request_filename is not exist";
}
}
测试:
5.1.2、set 指令
指定key并给其定义一个变量,变量可以调用Nginx内置变量赋值给key
另外set定义格式为set $key value,value可以是text, variables和两者的组合。
5.1.3、break指令
- 注意: 如果break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
location /break {
default_type text/html;
set $name zpy;
echo $name;
if ( $http_user_agent = "curl/7.76.1" ){
break;
}
set $id 666;
echo $id;
}
测试:
[root@nginx conf]# curl var.timingzpy.org/break
zpy[root@nginx conf]# curl -A "firefox" var.timingzpy.org/break
zpy
666
5.1.4、return 指令
location /return {
default_type text/html;
if ( !-e $request_filename){
return 301 http://www.baidu.com;
}
echo "$request_filename is exist";
}
测试:
5.2、rewrite 指令
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
- 通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,
- rewrite主要是针对用户请求的URL或者是URI做具体处理
- 如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查
- 被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的 标志位用于控制此循环机制
5.2.1、rewrite flag 使用介绍
利用nginx的rewrite的指令,可以实现url的重新跳转。
rewrite有四种不同的flag,分别是redirect(临时 重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型。
- 跳转型指由客户端浏览器重新对新地址进行请求
- 代理型是在WEB服务器内部实现跳转
redirect:
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent:
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端
#由客户端重新发起请求,状态码:301
break:
#重写完成后,停止对当前URL在当前location中后续的其它重写操作
#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用
#适用于一个URL一次重写。
last:
#重写完成后,停止对当前URI在当前location中后续的其它重写操作
#而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户
5.2.2、域名永久(permanent)与临时重定向(redirect)
location / {
root /data/web/var;
index index.html;
rewrite / http://www.timinglee.com permanent;
#rewrite / http://www.timinglee.com redirect;
}
location / {
root /data/web/var;
index index.html;
#rewrite / http://www.timinglee.com permanent;
rewrite / http://www.timinglee.com redirect;
}
5.2.3、break 与 last
访问break请求被rewrite至test1,而访问test1转递请求再次被rewrite发送至test2,此测试last和break 分别有什么区别
[root@nginx conf.d]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx conf.d]# echo test1 > /data/web/html/test1/index.html
[root@nginx conf.d]# echo test2 > /data/web/html/test2/index.html
[root@nginx conf.d]# echo last > /data/web/html/last/index.html
[root@nginx conf.d]# echo break > /data/web/html/break/index.html[root@nginx conf.d]# vim vars.conf(自己创建的子配置文件)
server {
listen 80;
server_name var.timingzpy.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 {
root /data/web/html;
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1;
}location /test1 {
default_type test/html;
return 666 "hahahahaha";
}location /test2 {
root /data/web/html;
}
}
5.2.4、自动跳转 https
在自己创建的子配置文件中
server {
listen 80;
listen 443 ssl;
server_name www.timinglee.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/timingzpy.org.crt;
ssl_certificate_key /usr/local/nginx/certs/timingzpy.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;location / {
if ( $scheme = http ){
rewrite / https://$host redirect;
}
}
}
5.2.5、判断文件是否存在
location / {
if ( $scheme = http ){
rewrite /(.*) https://$host/$1 redirect;
}if ( !-e $request_filename ){
rewrite /(.*) https://$host/index.html redirect;
}
}
5.3、防盗链
官方文档:https://nginx.org/en/docs/http/ngx_http_referer_module.html
cute.jpg:
haha.jpg:
1、实现盗链
#新建一个主机172.25.254.10,盗取另一台主机www.timingzpy.org/images/cute.jpg的图片 [root@test ~]# yum install httpd -y
[root@test ~]# 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.timingzpy.org/images/cute.jpg" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.timingzpy.org>狂点小张</a>彩票中奖</p>
</body></html>
[root@test1 ~]# systemctl restart httpd
2、实现防盗链
nginx的子配置文件中编写
[root@nginx ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
listen 443 ssl;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/timingzpy.org.crt;
ssl_certificate_key /usr/local/nginx/certs/timingzpy.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;location /images {
valid_referers none blocked server_names *.timingzpy.org ~/.baidu/.;
if ( $invalid_referer ){
rewrite ^/ http://www.timingzpy.org/haha.jpg;
}
}
}[root@nginx conf.d]# nginx -s reload
六、Nginx 反向代理功能
6.1、实现 http 反向代理
官方文档: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
6.1.1、http 协议反向代理
6.1.1.1、反向代理配置参数
6.1.1.2、反向代理单台 web 服务器
要求:将用户对域 www.timinglee.org 的请求转发给后端服务器处理
#再新建一个主机172.25.254.20,做后端服务器
[root@test ~]# echo test 172.25.254.10 > /var/www/html/index.html
[root@test1 ~]# yum install httpd -y
[root@test1 ~]# echo test1 172.25.254.20 > /var/www/html/index.html
在主配置文件中更改端口号
[root@test1 ~]# vim /etc/httpd/conf/httpd.conf
[root@test1 ~]# systemctl restart httpd
[root@nginx conf.d]# vim vars.conf(自己的子配置文件)
server {
listen 80;
server_name www.timingzpy.org;location / {
proxy_pass http://172.25.254.10:80;
}
}
6.1.1.3、指定 location 实现反向代理
server {
listen 80;
server_name www.timingzpy.org;location / {
proxy_pass http://172.25.254.10:80;
}location /static {
proxy_pass http://172.25.254.20:8080;
}
}
6.1.1.4、针对特定的资源实现代理
动静分离
[root@test ~]# yum install php -y
编辑vim格式
[root@test ~]# vim ~/.vimrc
[root@test ~]# cat ~/.vimrc
set ts=4 ai sw=4
[root@test ~]# vim /var/www/html/index.php
[root@test ~]# cat /var/www/html/index.php
<?php
phpinfo();
?>
[root@test ~]# systemctl restart httpd
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;
}
}
6.1.1.5、缓存功能
缓存功能默认关闭状态,需要先动配置才能启用
proxy_cache zone_name | off; 默认off #指明调用的缓存,或关闭缓存机制;
proxy_cache_key string; #缓存中用于“键”的内容
proxy_cache_valid [code ...] time; #定义对特定响应码的响应内容的缓存时长,定义在http{...}中
proxy_cache_path; #定义可用于proxy功能的缓存
keys_zone=proxycache:20m #指内存中缓存的大小,主要用于存放key和metadata
inactive=120s #缓存有效时间 max_size=10g; #最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
6.1.1.4.1 非缓存场景压测
172.25.254.20:
[root@test1 ~]# cd /var/www/html/static
[root@test1 static]# cat /var/log/messages > ./log.html[root@test1 static]# ls
index.html log.html
172.25.254.10:
[root@test ~]# ab -n1000 -c100 http://www.timingzpy.org/static/index.html
Server Software: Apache/2.4.57
Server Hostname: www.timingzpy.org
Server Port: 80Document Path: /static/index.html
Document Length: 196 bytesConcurrency Level: 100
Time taken for tests: 0.332 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 1000
Total transferred: 394000 bytes
HTML transferred: 196000 bytes
Requests per second: 3012.11 [#/sec] (mean)
Time per request: 33.199 [ms] (mean)
Time per request: 0.332 [ms] (mean, across all concurrent requests)
Transfer rate: 1158.96 [Kbytes/sec] received
6.1.1.4.2 准备缓存配置
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
#gzip on;proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g; #配置在nginx.conf http配置段
[root@nginx conf.d]# vim vhosts.conf
[root@nginx conf.d]# cat vhosts.conf
server {
listen 80;
server_name www.timingzpy.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; #对指定的数据进行MD5的运算做为缓存的key
proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多长时间
proxy_cache_valid any 1m; #除指定的状态码返回的数据以外的缓存多长时间,必须设置, 否则不会缓存
}
}[root@nginx ~]# nginx -s reload
#/data/nginx/proxycache/ 目录会自动生成
[root@nginx ~]# ll /usr/local/nginx/proxy_cache/ -d
drwx------. 2 nginx root 6 Aug 20 16:08 /usr/local/nginx/proxy_cache/
[root@nginx ~]# tree /usr/local/nginx/proxy_cache/
/usr/local/nginx/proxy_cache/0 directories, 0 files
6.1.1.4.3、访问并验证缓存文件
[root@test ~]# ab -n1000 -c100 http://www.timingzpy.org/static/index.html
Server Software: Apache/2.4.57
Server Hostname: www.timingzpy.org
Server Port: 80Document Path: /static/index.html
Document Length: 196 bytesConcurrency Level: 100
Time taken for tests: 0.321 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 1000
Total transferred: 394000 bytes
HTML transferred: 196000 bytes
Requests per second: 3113.35 [#/sec] (mean)
Time per request: 32.120 [ms] (mean)
Time per request: 0.321 [ms] (mean, across all concurrent requests)
Transfer rate: 1197.91 [Kbytes/sec] received#验证缓存目录结构及文件大小
[root@nginx ~]# tree /apps/nginx/proxy_cache/ /apps/nginx/proxy_cache/ └── e └── 50 └── 99 └── 319432ef3663735a9d3cb4e0c1d9950e 3 directories, 0 files
6.1.2 http 反向代理负载均衡
官方文档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
在上一个节中Nginx可以将客户端的请求转发至单台后端服务器但是无法转发至特定的一组的服务器,而 且不能对后端服务器提供相应的服务器状态监测。
Nginx 可以基于ngx_http_upstream_module模块提 供服务器分组转发、权重分配、状态监测、调度算法等高级功能。
[root@nginx ~]# nginx -V
nginx version: nginx/1.26.1
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
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --add-module=/root/echo-nginx-module-0.63 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
6.1.2.1 http upstream配置参数
在server模块之上
upstream backend(名称) {
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而不用重启
算法:
hash KEY [consistent];
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
#设定后端服务器的权重为5
server backend1.example.com weight=5;
#尝试连接1次等30s再次连接,3次以后没连上,视为这台主机下线(后端检测)
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
#访问套接字
server unix:/tmp/backend3;
#当上面的所有server访问不了时,这个就生效
server backup1.example.com backup;
}
6.1.2.2、后端多台 web服务器
环境说明:
172.25.254.100 #Nginx 代理服务器
172.25.254.10 #后端web A,Apache部署
172.25.254.20 #后端web B,Apache部
部署后端 Apache服务器:
yum install httpd -y
echo "web1 172.25.254.20" > /var/www/html/index.html
systemctl enable --now httpd
配置 nginx 反向代理:
注意: 本节实验过程中先关闭缓存
[root@nginx conf.d]# vim vhosts.conf
upstream webcluster {
#ip_hash;hash $request_uri consistent;
server 172.25.254.10:80 max_fails=3 fail_timeout=15s;
server 172.25.254.20:8080 max_fails=3 fail_timeout=15s;
#server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.timingzpy.org;location / {
proxy_pass http://webcluster;
}
}[root@nginx conf.d]# nginx -s reload
测试:
6.1.2.3、基于Cookie 实现会话绑定
[root@nginx conf.d]# vim vhosts.conf
upstream webcluster {
hash $cookie_zpy;
server 172.25.254.10:80 max_fails=3 fail_timeout=15s;
server 172.25.254.20:8080 max_fails=3 fail_timeout=15s;
}
server {
listen 80;
server_name www.timingzpy.org;location / {
proxy_pass http://webcluster;
}
}
测试:
6.2、实现 Nginx 四层负载均衡
Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于 DNS的域名解析,其配置方式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp 负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、 调度算法等高级功能。
官方文档:http:// https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html
如果编译安装,需要指定 --with-stream 选项才能支持ngx_stream_proxy_module模块
6.2.1 tcp负载均衡配置参数
stream { #定义stream相关的服务;
Context:main
upstream backend { #定义后端服务器
hash $remote_addr consistent; #定义调度算法
server backend1.example.com:12345 weight=5; #定义具体server
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}
upstream dns { #定义后端服务器
server 10.0.0.1:53; #定义具体server
server dns.example.com:53;
}
server { #定义server
listen 12345; #监听IP:PORT
proxy_connect_timeout 1s; #连接超时时间
proxy_timeout 3s; #转发超时时间
proxy_pass backend; #转发到具体服务器组
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}
6.2.2、udp 负载均衡实例: DNS
后端服务器安装 DNS
172.25.254.10:
[root@test ~]# dnf install bind -y
更改主配置文件
[root@test ~]# vim /etc/named.conf[root@test ~]# vim /etc/named.rfc1912.zones
[root@test ~]# cd /var/named
[root@test named]# cp named.localhost timingzpy.org.zone -p
[root@test named]# vim timingzpy.org.zone[root@test named]# systemctl start named
[root@test named]# dig www.timingzpy.org @172.25.254.10这样就配置完成了,为了方便,可以直接发送给172.25.254.20。
[root@test named]# scp -p /etc/named.{conf,rfc1912.zones} root@172.25.254.20:/etc/
[root@test named]# scp -p /var/named/timingzpy.org.zone root@172.25.254.20:/var/named/timingzpy.org.zone
172.25.254.20:
[root@test ~]# dnf install bind -y
[root@test1 named]# vim /var/named/timingzpy.org.zone
[root@test1 named]# systemctl start named
[root@test1 named]# dig www.timingzpy.org @172.25.254.20
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
include "/usr/local/nginx/tcpconf.d/*.conf";[root@nginx ~]# mkdir -p /usr/local/nginx/tcpconf.d
nginx的子配置文件:
stream {
upstream dns {
server 172.25.254.10:53 max_fails=3 fail_timeout=15s;
server 172.25.254.20:53 max_fails=3 fail_timeout=15s;
}
server{
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}}
将nginx配置dns的子配置文件移动到这个文件下
[root@nginx conf.d]# mv dns.conf /usr/local/nginx/tcpconf.d/
[root@nginx tcpconf.d]# 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 tcpconf.d]# nginx -s reload这样就可以了
测试:
6.2.3、负载均衡实例: MySQL
10/20:
[root@test named]# dnf install mariadb-server -y[root@test1 named]# vim /etc/my.cnf.d/mariadb-server.cnf
create user zpy@'%' identified by 'zpy';
grant all on *.* to zpy@'%';
我是在上面配置dns的文件里接着写的
nginx:
stream {
upstream dns {
server 172.25.254.10:53 max_fails=3 fail_timeout=15s;
server 172.25.254.20:53 max_fails=3 fail_timeout=15s;
}
upstream mysql {
server 172.25.254.10:3306 max_fails=3 fail_timeout=15s;
server 172.25.254.20:3306 max_fails=3 fail_timeout=15s;
}
server {
listen 3306;
proxy_timeout 60s;
proxy_pass mysql;
}
server{
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
[root@nginx conf.d]# nginx -s reload[root@nginx ~]# netstat -antlupe | grep 3306
下载mysql命令,要不然连不了
[root@nginx ~]# yum install mariadb -y
测试:
[root@nginx ~]# mysql -u zpy -p -h 172.25.254.100
[root@nginx ~]# mysql -u zpy -p -h 172.25.254.100
6.3、实现 FastCGI
6.3.1 FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处
fastcgi_pass address:port;
#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in location
fastcgi_index name;
#fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_param parameter value [if_not_empty];
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义 key
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
6.3.2、Nginx与php-fpm在同一服务器
源码编译PHP
1、上传PHP压缩包,解压
cd php-8.3.9
2、#利用yum解决php依赖
yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-develdnf whatprovieds oniguruma-devel
oniguruma-devel没有软件包需要下载上次解压cd /mnt
wget https://mirrors.aliyun.com/rockylinux/9.4/devel/x86_64/kickstart/Packages/o/oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
yum localinstall oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm3、#解压源码并安装
./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-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemdmake && make install
php相关配置优化
cd /usr/local/php/etc
cp -p php-fpm.conf.default php-fpm.conf
vim php-fpm.conf(要改)
cd php-fpm.d/
cp www/.conf.default www.conf -p
vim www.conf更改时区
[root@nginx ~]# cd php-8.3.9/
[root@nginx php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@nginx php-8.3.9]# cd /usr/local/php/etc/
[root@nginx etc]# ls
php-fpm.conf php-fpm.conf.default php-fpm.d php.ini
[root@nginx etc]# vim php.ini
生成启动脚本
[root@nginx ~]# cd php-8.3.9/sapi/fpm/
[root@nginx fpm]# ls
config.m4 LICENSE php-fpm.conf status.html.in
CREDITS Makefile.frag php-fpm.conf.in tests
fpm php-fpm php-fpm.service www.conf
init.d.php-fpm php-fpm.8 php-fpm.service.in www.conf.in
init.d.php-fpm.in php-fpm.8.in status.html
[root@nginx fpm]# cp php-fpm.service /lib/systemd/system/现在启动还报错,显示这个文件写入不了为只读
需要将这个命令注释掉,再启动
[root@nginx fpm]# vim /lib/systemd/system/php-fpm.service
[root@nginx fpm]# systemctl daemon-reload
[root@nginx fpm]# systemctl start php-fpm
添加环境变量
[root@nginx php]# vim ~/.bash_profile
[root@nginx php]# 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:/usr/local/php/bin:/usr/local/php/sbin
[root@nginx php]# source ~/.bash_profile
php测试页面
mkdir -p /data/web/php
cd /data/web/php
vim index.php
<?php
phpinfo()
?>
PHP结合nginx,Nginx配置转发
[root@nginx conf.d]# vim vhosts.conf
[root@nginx conf.d]# cat vhosts.conf
server {
listen 80;
server_name www.timingzpy.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;
}
}
[root@nginx conf]# nginx -s reload
测试:
6.3.3 php的动态扩展模块(php的缓存模块)
软件下载:http://pecl.php.net/package/memcache
安装memcache模块
[root@Nginx memcache-8.2]# yum install autoconf -y
[root@nginx ~]# cd memcache-8.2/
[root@nginx memcache-8.2]# phpize
Configuring for:
PHP Api Version: 20230831
Zend Module Api No: 20230831
Zend Extension Api No: 420230831
[root@nginx memcache-8.2]# ./configure && make && make install
[root@nginx memcache-8.2]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20230831/
memcache.so opcache.so
[root@nginx ~]# systemctl restart php-fpm.service
复制测试文件到nginx发布目录中
[root@nginx memcache-8.2]# cp example.php memcache.php /data/web/php/
[root@Nginx memcache-8.2]# vim memcache.php
define('ADMIN_USERNAME','admin');
define('ADMIN_PASSWORD','zpy');
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
$MEMCACHE_SERVERS[] = '127.0.0.1:11211';
$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211';
[root@nginx memcache-8.2]# cd /data/web/php/
[root@nginx php]# ls
example.php index.php memcache.php
配置php加载memcache模块
[root@nginx ~]# vim /usr/local/php/etc/php.ini
部署memcached
[root@nginx ~]# dnf install memcached -y
[root@nginx php]# systemctl enable --now memcached.service
测试:
访问 http://php.timinglee.org/example.php 不断刷新
访问 http://php.timinglee.org/memcache.php 查看命中效
性能对比
[root@nginx etc]# ab -n500 -c10 http://www.timingzpy.org/index.php
Concurrency Level: 10
Time taken for tests: 0.625 seconds
Complete requests: 500
Failed requests: 41
(Connect: 0, Receive: 0, Length: 41, Exceptions: 0)
[root@nginx etc]# ab -n500 -c10 http://www.timingzpy.org/example.php
Concurrency Level: 10
Time taken for tests: 0.686 seconds
Complete requests: 500
Failed requests: 0
6.3.4、php高速缓存
将memcache前置
upstream memcache {
server 127.0.0.1:11211;
keepalive 512;
}
server {
listen 80;
server_name www.timingzpy.org;
root /data/web/html;
index index.html;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$ {
root /data/web/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;
}
}
测试:
7、nginx 二次开发版本
官网: http://openresty.org/cn/
Nginx 是俄罗斯人发明的, Lua 是巴西几个教授发明的,中国人章亦春把 LuaJIT VM 嵌入到Nginx 中, 实现了 OpenResty 这个高性能服务端解决方案。
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方 模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服 务和动态网关。
7.1 编译安装openresty
安装编译环境
[root@nginx ~]# dnf -yq install gcc pcre-devel openssl-devel perl
下载源码,解压
[root@nginx ~]# cd /usr/local/src
[root@nginx src]# wget https://openresty.org/download/openresty-1.17.8.2.tar.gz[root@nginx src]# ls
openresty-1.17.8.2.tar.gz
[root@nginx src]# tar xf openresty-1.17.8.2.tar.gz
编译OpenResty
选择需要的插件启用, –with-Components 激活组件,–without 则是禁止组件 ,–add-module是安装第三方模块
[root@nginx src]# cd openresty-1.17.8.2/
[root@nginx openresty-1.17.8.2]# ./configure --prefix=/usr/local/openresty --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module[root@nginx openresty-1.17.8.2]# make && make install