前言
- 学习视频:尚硅谷Nginx教程(亿级流量nginx架构设计)
- 本内容仅用于个人学习笔记,如有侵扰,联系删
- 学习文档:
- 云原生系列 - Nginx(基础篇)
1、简介
1.1、背景介绍
Nginx(enginex)是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004 年10月4日。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx1.0.4发布。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
1.2、名词解释
-
WEB服务器:
WEB服务器也叫网页服务器,英文名叫Web Server,主要功能是为用户提供网上信息浏览服务。 -
HTTP:
HTTP是超文本传输协议的缩写,是用于从WEB服务器传输超文本到本地浏览器的传输协议,也是互联网上应用最为广泛的一种网络协议。HTTP是一个客户端和服务器端请求和应答的标准,客户端是终端用户,服务端是网站,通过使用Web浏览器、网络爬虫或者其他工具,客户端发起一个到服务器上指定端口的HTTP请求。 -
POP3/SMTP/IMAP:
POP3(Post Offic Protocol 3)邮局协议的第三个版本,
SMTP(Simple Mail Transfer Protocol)简单邮件传输协议,
IMAP(Internet Mail Access Protocol)交互式邮件存取协议,
通过上述名词的解释,我们可以了解到Nginx也可以作为电子邮件代理服务器。 -
反向代理
正向代理
反向代理
1.3、Nginx的优点
- 速度更快、并发更高
单次请求或者高并发请求的环境下,Nginx都会比其他Web服务器响应的速度更快。一方面在正常情况下,单次请求会得到更快的响应,另一方面,在高峰期(如有数以万计的并发请求),Nginx比其他Web服务器更快的响应请求。Nginx之所以有这么高的并发处理能力和这么好的性能原因在于Nginx采用了多进程和I/O多路复用(epoll)的底层实现。 - 配置简单,扩展性强
Nginx的设计极具扩展性,它本身就是由很多模块组成,这些模块的使用可以通过配置文件的配置来添加。这些模块有官方提供的也有第三方提供的模块,如果需要完全可以开发服务自己业务特性的定制模块。 - 高可靠性
Nginx采用的是多进程模式运行,其中有一个master主进程和N多个worker进程,worker进程的数量我们可以手动设置,每个worker进程之间都是相互独立提供服务,并且master主进程可以在某一个worker进程出错时,快速去"拉起"新的worker进程提供服务。 - 热部署
现在互联网项目都要求以7*24小时进行服务的提供,针对于这一要求,Nginx也提供了热部署功能,即可以在Nginx不停止的情况下,对Nginx进行文件升级、更新配置和更换日志文件等功能。 - 成本低、BSD许可证
BSD是一个开源的许可证,世界上的开源许可证有很多,现在比较流行的有六种分别是GPL、BSD、MIT、Mozilla、Apache、LGPL。这六种的区别是什么,我们可以通过下面一张图来解释下:
Nginx本身是开源的,我们不仅可以免费的将Nginx应用在商业领域,而且还可以在项目中直接修改Nginx的源码来定制自己的特殊要求。这些点也都是Nginx为什么能吸引无数开发者继续为Nginx来贡献自己的智慧和青春。OpenRestry [Nginx+Lua] Tengine[淘宝]
1.4、Nginx的功能特性及常用功能
Nginx提供的基本功能服务从大体上归纳为"基本HTTP服务"、“高级HTTP服务”和"邮件服务"等三大类。
- 基本HTTP服务
Nginx可以提供基本HTTP服务,可以作为HTTP代理服务器和反向代理服务器,支持通过缓存加速访问,可以完成简单的负载均衡和容错,支持包过滤功能,支持SSL等。- 处理静态文件、处理索引文件以及支持自动索引;
- 提供反向代理服务器,并可以使用缓存加上反向代理,同时完成负载均衡和容错;
- 提供对FastCGI、memcached等服务的缓存机制,,同时完成负载均衡和容错;
- 使用Nginx的模块化特性提供过滤器功能。Nginx基本过滤器包括gzip压缩、ranges支持、chunked响应、XSLT、SSI以及图像缩放等。其中针对包含多个SSI的页面,经由FastCGI或反向代理,SSI过滤器可以并行处理。
- 支持HTTP下的安全套接层安全协议SSL.
- 支持基于加权和依赖的优先权的HTTP/2
- 高级HTTP服务
- 支持基于名字和IP的虚拟主机设置
- 支持HTTP/1.0中的KEEP-Alive模式和管线(PipeLined)模型连接
- 自定义访问日志格式、带缓存的日志写操作以及快速日志轮转。
- 提供3xx~5xx错误代码重定向功能
- 支持重写(Rewrite)模块扩展
- 支持重新加载配置以及在线升级时无需中断正在处理的请求
- 支持网络监控
- 支持FLV和MP4流媒体传输
- 邮件服务
Nginx提供邮件代理服务也是其基本开发需求之一,主要包含以下特性:
- 支持IMPA/POP3代理服务功能
- 支持内部SMTP代理服务功能
1.5、Nginx常用的功能模块
- 静态资源部署
- Rewrite地址重写
正则表达式 - 反向代理
- 负载均衡
- 轮询、加权轮询、ip_hash、url_hash、fair
- Web缓存
- 环境部署
- 高可用的环境
- 用户认证模块…
1.6、Nginx的核心组成
- nginx二进制可执行文件
- nginx.conf配置文件
- error.log错误的日志记录
- access.log访问日志记录
2、Nginx的安装
2.1、Nginx环境准备
-
虚拟机系统安装
虚拟机环境安装准备
1. VMware WorkStation
2. Centos7
3. MobaXterm
4. 网络VMware中安装CentOS7请参考文档:在VMware中安装CentOS7(超详细的图文教程)
-
确认centos的内核
准备一个内核为2.6及以上版本的操作系统,因为linux2.6及以上内核才支持epoll,而Nginx需要解决高并发压力问题是需要用到epoll,所以我们需要有这样的版本要求。
我们可以使用uname -a
命令来查询linux的内核版本。[root@VM-16-14-centos ~]# uname -a Linux VM-16-14-centos 3.10.0-1160.88.1.el7.x86_64 #1 SMP Tue Mar 7 15:41:52 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
-
确保centos能联网
[root@VM-16-14-centos ~]# ping www.baidu.com PING www.a.shifen.com (180.101.50.188) 56(84) bytes of data. 64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=1 ttl=49 time=11.5 ms 64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=2 ttl=49 time=11.5 ms 64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=3 ttl=49 time=11.6 ms 64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=4 ttl=49 time=11.6 ms
-
确认关闭防火墙
这一项的要求仅针对于那些对linux系统的防火墙设置规则不太清楚的,建议大家把防火墙都关闭掉,因为我们此次课程主要的内容是对Nginx的学习,把防火墙关闭掉,可以省掉后续Nginx学习过程中遇到的诸多问题。
关闭的方式有如下两种:# 1、关闭运行的防火墙,系统重新启动后,防火墙将重新打开 systemctl stop firewalld # 2、永久关闭防火墙,,系统重新启动后,防火墙依然关闭 systemctl disable firewalld # 3、查看防火墙状态 systemctl status firewalld
-
确认停用selinux
selinux(security-enhanced linux),美国安全局对于强制访问控制的实现,在linux2.6内核以后的版本中,selinux已经成功内核中的一部分。可以说selinux是linux史上最杰出的新安全子系统之一。虽然有了selinux,我们的系统会更安全,但是对于我们的学习Nginx的历程中,会多很多设置,所以这块建议大家将selinux进行关闭。
sestatus
查看状态[root@VM-16-14-centos ~]# sestatus SELinux status: disabled
如果查看不是disabled状态,我们可以通过修改配置文件来进行设置,修改SELINUX=disabled,然后重启下系统即可生效。
vim /etc/selinux/config
2.2、Nginx的发行版本
常用版本分为四大阵营:
-
Nginx 开源版 | https://nginx.org/:赤裸裸的Web服务器、反向代理、负载均衡(功能少,开发难度大)
-
Nginx Plus 商业版 | https://www.nginx.com/:什么都有全家桶(付费版本)
-
OpenResty | https://openresty.org/cn/:是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。
-
Tengine | https://tengine.taobao.org/:淘宝二开的Nginx。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。
2.3、编译安装Nginx(开源版)
-
下载地址:nginx: download | https://nginx.org/en/download.html
-
配置编译安装环境
tar zxvf nginx-1.20.2.tar.gz
[root@localhost ~]# cd nginx-1.20.2 [root@localhost nginx-1.20.2]# ll 总用量 788 drwxr-xr-x 6 1001 1001 326 8月 14 10:53 auto -rw-r--r-- 1 1001 1001 312251 11月 16 2021 CHANGES -rw-r--r-- 1 1001 1001 476577 11月 16 2021 CHANGES.ru drwxr-xr-x 2 1001 1001 168 8月 14 10:53 conf -rwxr-xr-x 1 1001 1001 2590 11月 16 2021 configure drwxr-xr-x 4 1001 1001 72 8月 14 10:53 contrib drwxr-xr-x 2 1001 1001 40 8月 14 10:53 html -rw-r--r-- 1 1001 1001 1397 11月 16 2021 LICENSE drwxr-xr-x 2 1001 1001 21 8月 14 10:53 man -rw-r--r-- 1 1001 1001 49 11月 16 2021 README drwxr-xr-x 9 1001 1001 91 8月 14 10:53 src
根据编译安装报错,可以判断需要什么环境依赖
以下是关于编译安装的基础知识:
configure文件:这个文件是一个Shell脚本,用于检测系统环境、配置编译选项以及生成相应的Makefile文件。
Makefile文件是软件工程中的一种自动化构建工具文件,主要用于Unix-like操作系统(如Linux、BSD等)和一些集成开发环境(IDEs),用于管理和自动化编译、链接程序的过程。在Makefile中,开发者定义了一系列规则来指导make工具如何编译和链接源代码文件,以生成最终的目标文件(通常是可执行文件或库文件)。
Makefile的核心功能包括:
依赖关系:声明源代码文件之间的依赖关系,当某个源文件或其依赖的头文件发生变化时,仅重新编译受影响的部分而不是整个项目。
规则:定义如何从源文件生成目标文件的规则,包括编译器选项、编译命令、链接命令等。
自动化:通过比较文件的修改时间和目标文件的存在与否,make能自动判断哪些目标需要更新,并执行相应的命令。
目标:可以定义多种目标,如编译调试版、发布版,或者执行测试、清理等任务。
变量和函数:Makefile支持变量和函数,可以用来简化命令行参数和路径名的管理。
模式规则:允许定义通用的转换规则,适用于多个源文件到目标文件的转换情况。
在实际使用中,程序员通过编写Makefile来组织和控制整个项目的构建流程,只需简单地运行make命令,make工具就会读取Makefile文件,分析依赖关系,并执行必要的编译和链接步骤来生成最终的产品。第一次报错+排查(注意看代码注释)
安装gcc[root@localhost nginx-1.20.2]# ./configure --prefix=/usr/local/nginx checking for OS + Linux 3.10.0-862.el7.x86_64 x86_64 checking for C compiler ... not found # 缺少C语言编译器 ./configure: error: C compiler cc is not found # 配置Yum curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo yum install -y epel-release # gcc是c语言编译器的一种 yum install -y gcc
第二次报错+排查(注意看代码注释)
安装perl库[root@localhost nginx-1.20.2]# ./configure --prefix=/usr/local/nginx ... ... checking for PCRE library in /usr/pkg/ ... not found checking for PCRE library in /opt/local/ ... not found ./configure: error: the HTTP rewrite module requires the PCRE library. # 缺少pcpe库 You can either disable the module by using --without-http_rewrite_module option, or install the PCRE library into the system, or build the PCRE library statically from the source with nginx by using --with-pcre=<path> option. # 安装 pcre yum install -y pcre pcre-devel
第三次报错+排查(注意看代码注释)
安装zlib库# 再次执行编译安装 [root@localhost nginx-1.20.2]# ./configure --prefix=/usr/local/nginx checking for zlib library ... not found ./configure: error: the HTTP gzip module requires the zlib library. # 确实zlib库 You can either disable the module by using --without-http_gzip_module option, or install the zlib library into the system, or build the zlib library statically from the source with nginx by using --with-zlib=<path> option. [root@localhost nginx-1.20.2]# yum install -y zlib zlib-devel # 再次执行,成功安装完成,并可以看到当前目录下生成了Makefile文件 [root@localhost nginx-1.20.2]# ./configure --prefix=/usr/local/nginx creating objs/Makefile Configuration summary + using system PCRE library + OpenSSL library is not used + using system zlib library nginx path prefix: "/usr/local/nginx" nginx binary file: "/usr/local/nginx/sbin/nginx" nginx modules path: "/usr/local/nginx/modules" nginx configuration prefix: "/usr/local/nginx/conf" nginx configuration file: "/usr/local/nginx/conf/nginx.conf" nginx pid file: "/usr/local/nginx/logs/nginx.pid" nginx error log file: "/usr/local/nginx/logs/error.log" nginx http access log file: "/usr/local/nginx/logs/access.log" nginx http client request body temporary files: "client_body_temp" nginx http proxy temporary files: "proxy_temp" nginx http fastcgi temporary files: "fastcgi_temp" nginx http uwsgi temporary files: "uwsgi_temp" nginx http scgi temporary files: "scgi_temp"
-
编译安装
# make命令的功能是编译内核或源码文件。 make # 安装已经编译好的程序。复制文件树中到文件到指定的位置 make install # 卸载已经编译好的程序。暂不执行 make uninstall
2.4、操作与配置
-
启动Nginx
进入安装好的目录/usr/local/nginx/sbin
./nginx 启动 ./nginx -s stop 快速停止 ./nginx -s quit 优雅关闭,在退出前完成已经接受的连接请求 ./nginx -s reload 重新加载配置 ./nginx -t 测试配置文件语法是否正确
nginx -s reload
命令看似只是重新加载配置。其实是创建了新线程Work来替换的老的线程Work。[root@localhost sbin]# ./nginx [root@localhost sbin]# ps -aux| grep nginx root 12189 0.0 0.0 20572 616 ? Ss 13:22 0:00 nginx: master process ./nginx nobody 12190 0.0 0.0 21016 1312 ? S 13:22 0:00 nginx: worker process root 12192 0.0 0.0 112824 984 pts/0 S+ 13:22 0:00 grep --color=auto nginx
访问地址:http://192.168.119.128/
浏览器如果访问不到,请关闭防火墙
-
关于防火墙
防火墙内网可以不开。一般IP需要暴露在外网才开。如果需要防范内部人员也可开启。# 关闭防火墙 systemct1 stop firewalld.service # 禁止防火墙开机启动 systemct1 disable firewalld.service # 放行端口 firewa11-cmd --zone=public --add-port=80/tcp --permanent # 重启防火墙 firewa11-cmd --reload
-
安装成系统服务
- 创建服务脚本
# 编辑Nginx系统服务文件 vi /usr/lib/systemd/system/nginx.service
- 服务脚本内容
[Unit] Description=nginx - web server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s stop PrivateTmp=true [Install] WantedBy=multi-user.target
- 重新加载系统服务
systemctl daemon-reload
- 启动Nginx
注意:使用systemctl
命令启动Nginx前,请使用./nginx -s stop
命令将原方式启动的Nginx关闭./nginx -s stop
systemctl start nginx
- 设置开机启动
systemctl enable nginx
- 查看nginx状态
systemctl status nginx
- 创建服务脚本
3、Nginx 基础使用
3.1、目录结构
进入Nginx的主目录我们可以看到这些文件夹
client_body_temp conf fastcgi_temp html logs proxy_temp sbin scgi_temp uwsgi_temp
-
临时文件
其中目录带有temp的字段是临时文件,是Nginx运行之后产生的,主要用来存放运行过程中的临时文件client_body_temp fastcgi_temp proxy_temp scgi_temp
带有
temp
目录的项在Nginx的目录结构中主要用于存储临时文件,这些目录与Nginx处理不同类型的请求时产生的临时数据相关。每个temp
目录对应于Nginx处理特定类型请求时的临时存储需求,具体说明如下:client_body_temp
: 存储客户端请求体的临时文件。当客户端发送POST请求,且请求体较大时,Nginx会先将请求体写入到这个目录下的临时文件中,然后再由Nginx处理或转发给后端服务器。fastcgi_temp
: 用于FastCGI请求的临时文件存储。当Nginx作为前端服务器,与后端FastCGI应用服务器(如PHP-FPM)交互时,可能会需要存储一些临时数据,比如上传的文件或者大请求体。proxy_temp
: 服务于HTTP代理和反向代理请求的临时文件。当Nginx作为代理服务器转发请求到后端,并且需要暂存请求或响应的内容时,会用到这个目录。scgi_temp
和uwsgi_temp
: 分别用于SCGI(Simple Common Gateway Interface)和uWSGI(Universal Web Server Gateway Interface)协议相关的临时文件存储。这两种协议类似于FastCGI,用于与不同的后端应用程序服务器通信。
这些临时文件夹的存在,使得Nginx能够高效处理各种类型的请求,尤其是在处理大数据量传输时,避免了直接在内存中存储大量数据,从而降低了系统内存的压力。需要注意的是,这些目录通常由Nginx服务运行的用户(如上面显示的nobody)拥有权限,以确保安全性和隔离性。在生产环境中,定期清理这些临时文件是非常重要的维护操作,以避免磁盘空间被无用的临时文件耗尽。
-
conf
用来存放配置文件相关[root@localhost nginx]# ll conf/ 总用量 68 -rw-r--r-- 1 root root 1077 8月 14 11:10 fastcgi.conf -rw-r--r-- 1 root root 1077 8月 14 11:10 fastcgi.conf.default -rw-r--r-- 1 root root 1007 8月 14 11:10 fastcgi_params -rw-r--r-- 1 root root 1007 8月 14 11:10 fastcgi_params.default -rw-r--r-- 1 root root 2837 8月 14 11:10 koi-utf -rw-r--r-- 1 root root 2223 8月 14 11:10 koi-win -rw-r--r-- 1 root root 5231 8月 14 11:10 mime.types -rw-r--r-- 1 root root 5231 8月 14 11:10 mime.types.default -rw-r--r-- 1 root root 2656 8月 14 11:10 nginx.conf # 主要配置文件,该文件可以引用其它配置文件 -rw-r--r-- 1 root root 2656 8月 14 11:10 nginx.conf.default -rw-r--r-- 1 root root 636 8月 14 11:10 scgi_params -rw-r--r-- 1 root root 636 8月 14 11:10 scgi_params.default -rw-r--r-- 1 root root 664 8月 14 11:10 uwsgi_params -rw-r--r-- 1 root root 664 8月 14 11:10 uwsgi_params.default -rw-r--r-- 1 root root 3610 8月 14 11:10 win-utf
-
html
用来存放静态文件的默认目录 html、css等[root@localhost nginx]# ll html/ 总用量 8 -rw-r--r-- 1 root root 494 8月 14 11:10 50x.html # Nginx访问出现错误时的提示页面 -rw-r--r-- 1 root root 612 8月 14 11:10 index.html # Nginx默认访问的文件
-
log
用来日志文件[root@localhost nginx]# ll logs/ 总用量 12 -rw-r--r-- 1 root root 417 8月 14 11:17 access.log # Nginx用户访问日志文件,所以访问都将记录在该文件中 -rw-r--r-- 1 root root 324 8月 14 11:19 error.log # Nginx访问报错时记录日志文件 -rw-r--r-- 1 root root 5 8月 14 11:19 nginx.pid # 记录Nginx的主进程的Pid的文件
验证nginx.pid文件是否保存的主进程Pid
可以看到nginx.pid文件内容,和nginx: master主进程ID一致。该文件为更具nginx: master主进程PID变化[root@localhost nginx]# cat logs/nginx.pid 12189 [root@localhost nginx]# ps -aux | grep nginx root 12189 0.0 0.0 20572 616 ? Ss 13:22 0:00 nginx: master process ./nginx nobody 12190 0.0 0.0 21016 1312 ? S 13:22 0:00 nginx: worker process root 12207 0.0 0.0 112824 988 pts/0 S+ 13:24 0:00 grep --color=auto nginx
-
sbin
nginx的主程序[root@localhost nginx]# ll sbin/ 总用量 3796 -rwxr-xr-x 1 root root 3883616 8月 14 11:10 nginx # Nginx程序启动文件
3.2、基本运行原理
主进程(Master Process)与工作进程(Worker Processes):
Master Process
:Nginx 启动时,首先会生成一个主进程。主进程主要负责管理子进程、加载和验证配置文件、维护工作进程池,以及响应信号(如重新加载配置、优雅关闭等)。主进程不直接参与处理客户端请求。Worker Processes
:主进程会根据配置文件中指定的数量创建多个工作进程。每个工作进程都能够独立处理客户端的请求,包括接收请求、处理请求、返回响应等。工作进程数量通常与服务器的CPU核心数相匹配,以充分利用硬件资源。
重新加载配置(reload操作):nginx.conf配置文件更改了,Master会将Worker进程Kill掉,Kill之前会留有一段时间让当前的Worker进程处理完手上的请求,不再接收新的请求了。Kill掉之后创建一个新的Worker进程,配置文件读取的也是最新的。
[root@localhost nginx]# ps -aux | grep nginx
root 12189 0.0 0.0 20572 616 ? Ss 13:22 0:00 nginx: master process ./nginx
nobody 12190 0.0 0.0 21016 1312 ? S 13:22 0:00 nginx: worker process
root 12207 0.0 0.0 112824 988 pts/0 S+ 13:24 0:00 grep --color=auto nginx
4、Nginx配置与应用场景
4.1、最小配置
4.1.1、初始配置文件(示例)
[root@localhost conf]# cat nginx.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
4.1.2、Nginx配置各个区域块解析
-
全局块(Outside of any http{} block)
- user: 指定运行 Nginx 工作进程的用户和组,默认为 nobody 或 www-data。
- worker_processes: 设置 Nginx 使用的工作进程数,通常与服务器的 CPU 核心数相匹配。
- error_log: 定义全局错误日志的文件路径及日志级别。
- pid: 设置 Nginx 主进程的 PID 文件路径。
-
Events
- worker_connections: 每个工作进程能同时打开的最大连接数。
- use epoll (Linux): 指定使用的事件处理机制,如epoll提高性能。
- events { … }: 控制 Nginx 如何处理连接。重要配置包括:
-
HTTP
-
include mime.types: 引入 MIME 类型映射文件。
-
default_type application/octet-stream: 设定默认的 MIME 类型,用于未明确定义类型的文件。
-
log_format: 自定义日志格式。
-
access_log: 定义访问日志的文件路径及格式。
-
sendfile on;: 开启高效文件传输模式,减少 CPU 使用。
未开启sendfile
开启后
-
keepalive_timeout: 设置 Keep-Alive 连接超时时间。
-
server_tokens off;: 关闭服务器版本号在错误页面的显示,增强安全性。
-
http { … }: 包含了所有与 HTTP 协议相关的配置。
-
include mime.types: 引入 MIME 类型映射文件。
-
default_type application/octet-stream: 设定默认的 MIME 类型,用于未明确定义类型的文件。
-
log_format: 自定义日志格式。
-
access_log: 定义访问日志的文件路径及格式。
-
sendfile on;: 开启高效文件传输模式,减少 CPU 使用。
-
keepalive_timeout: 设置 Keep-Alive 连接超时时间。
-
server_tokens off;: 关闭服务器版本号在错误页面的显示,增强安全性。
-
http { … }: 包含了所有与 HTTP 协议相关的配置。
-
-
Server
虚拟主机配置server { listen 80; 监听端口号 server_name example.com www.example.com; 主机名 location / { 匹配路径 root html; 文件根目录 index index.html index.htm; 默认页名称 } error_page 500 502 503 504 /50x.html; 报错编码对应页面 location = /50x.html { root html; } }
这只是 nginx.conf 文件中可能包含的部分配置示例。实际配置根据具体需求会更加复杂和多样化,可能还包括SSL证书配置、速率限制、缓存策略、Gzip压缩、rewrite规则等高级配置。每个配置指令的具体意义和可选参数,都可以在 Nginx 官方文档中找到详细的说明。
Nginx 官方文档:https://nginx.org/en/docs/
- listen 80;: 监听的端口号。
- server_name example.com www.example.com;: 服务器名称,用于域名解析。
- root /var/www/html;: 指定网站根目录。
- location / { … }: 定义不同URL路径的处理方式,如静态文件服务、反向代理等。
- root html;: root 指令指定了服务器根路径请求所对应的本地文件系统的根目录。在这个例子中,“html” 是一个目录名,它相对于 Nginx 安装目录(或在配置文件中通过 alias 指令指定的其他基路径)的相对路径。
- index index.html index.htm;: index 指令指定了当请求的URL是一个目录时,Nginx 应该优先尝试返回的默认文档列表。
- try_files $uri $uri/ =404;: 尝试访问请求的文件或目录,如果找不到则返回404错误。
- proxy_pass http://localhost:8000;: 如果是反向代理配置,则将请求转发给后端服务器。
- server { … }: 定义一个虚拟主机或监听的端口配置。
4.1.3、root和alias指令区别(面试题)
假设 root
设置为 /var/www/html
,且 location /images/
处理图像请求,那么请求 http://example.com/images/picture.jpg
会映射到文件系统路径 /var/www/html/images/picture.jpg
。
用户请求:http://example.com/images/picture.jpg
宿主机映射路径:/var/www/html/images/picture.jpg
location /images {
root /var/www/html;
index index.html index.htm;
}
若使用 alias /var/www/html/
在相同的 location /images/
中,同样的请求 http://example.com/images/picture.jpg
将直接映射到 /var/www/html/picture.jpg
,不会保留 location
中的 /images/
部分。
用户请求:http://example.com/images/picture.jpg
宿主机映射路径:/var/www/html/picture.jpg
location /images {
alias /var/www/html/;
index index.html index.htm;
}
4.1.4、最小化Nginx配置文件,这里只是将注释去掉了。
[root@localhost conf]# cat nginx.conf
worker_processes 1; # worker进程启动数量
events {
worker_connections 1024; # 单个worker进程的连接数
}
http {
include mime.types; # include可以将其它配置文件引入到当前配置文件当中。mime.types文件是记录的请求头类型,比如:text/html、text/css、application/json请求头,打开文件查看详情。
default_type application/octet-stream; # 如果请求头类型,没在mime.types文件记录,那么就走default_type定义的application/octet-stream类型(格式流)
sendfile on; # 使用linux的sendfi1e(socket,file,1en)高效网络传输,也就是数据0拷贝。
keepalive_timeout 65; # 持久连接(Keep-Alive)的超时时间。当客户端与Nginx服务器之间启用HTTP Keep-Alive连接时,允许在一个TCP连接上连续发送多个HTTP请求,而不是为每个请求都新建一个TCP连接。这样可以减少建立新连接的开销,提高HTTP请求的效率。
# 一个server指一个虚拟主机 vhost
server {
listen 80;
server_name localhost; # 指定主机的地址,可以是域名或IP
# location 用于根据客户端请求的URI(统一资源标识符)来匹配请求并执行相应的操作,如提供静态文件服务、代理请求到后端服务器、重定向等
location / {
root html; # root代表根目录,这里指的是/usr/local/nginx/html目录下
index index.html index.htm; # 默认访问的文件
}
error_page 500 502 503 504 /50x.html; # error_page指服务器端发生错误,比如返回500 502 503 504时,跳转到/50x.html文件。http://qiuyl.com/50x.html,但是上面的location /默认没有指定该文件,所以下面的location = /50x.html 判断后会在html目录找该文件。
location = /50x.html {
root html;
}
}
}
5、Nginx虚拟主机
Nginx 虚拟主机允许在一个单一的物理服务器上运行多个独立的网站或应用,每个都具有自己的域名、文档根目录、日志文件等,仿佛它们各自运行在独立的服务器上。Nginx 支持三种主要类型的虚拟主机配置:基于端口、基于域名和基于IP地址。
5.1、虚拟主机配置
-
环境准备
修改C:\Windows\System32\drivers\etc\
目录下的hosts文件
右击hosts文件查看属性,检查登录的Win系统用户是否有修改权限,没有则编辑修改权限即可编辑hosts映射
192.168.119.128 wts.com
创建虚拟主机站点目录:www和vod
[root@localhost /]# mkdir www [root@localhost /]# cd www [root@localhost www]# mkdir www [root@localhost www]# mkdir vod [root@localhost www]# ls vod www
编辑www的index.html
[root@localhost www]# cd www [root@localhost www]# pwd /root/www/www [root@localhost www]# vi index.html
this is www web site.
编辑vod的index.html
[root@localhost www]# cd .. [root@localhost www]# cd vod [root@localhost vod]# pwd /root/www/vod [root@localhost vod]# vi index.html
this is vod web site.
5.2、端口虚拟主机
注意:端口虚拟主机,端口不能一致
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 虚拟主机 vhost
server {
listen 80;
# 域名、主机名
server_name localhost;
location / {
root /www/www;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机 vhost
server {
listen 88;
# 域名、主机名
server_name localhost;
location / {
root /www/vod;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
重启nginx
systemctl reload nginx
浏览器访问
http://192.168.119.128:80
http://192.168.119.128:88/
5.3、域名虚拟主机
注意:域名虚拟主机,端口可一致
修改本地hosts映射
修改C:\Windows\System32\drivers\etc\
目录下的hosts文件
右击hosts文件查看属性,检查登录的Win系统用户是否有修改权限,没有则编辑修改权限即可
编辑hosts映射
192.168.119.128 wts01.com
192.168.119.128 wts02.com
修改nginx.conf配置
访问:http://wts01.com/
访问:http://wts02.com/
5.4、IP虚拟主机
在ens33网卡上添加一个IP
[root@VM-16-14-centos ~]# ip addr add 192.168.119.138/24 dev ens33
[root@VM-16-14-centos ~]#
[root@VM-16-14-centos ~]# ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.119.128/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.119.138/24 scope global secondary ens33
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 虚拟主机 vhost
server {
listen 192.168.119.128:80;
# 域名、主机名
server_name localhost;
location / {
root /www/www;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 虚拟主机 vhost
server {
listen 192.168.119.138:80;
# 域名、主机名
server_name localhost;
location / {
root /www/vod;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
浏览器访问不同IP返回不同页面
访问:http://192.168.119.128
访问:http://192.168.119.138
6、ServerName匹配规则
6.1、应用场景
如果我们有好几个域名(包含二级域名、泛域名),需要解析到相同的Server
(虚拟主机站点)或者不同的Server
,可以使用server_name
指令实现。
二级域名和泛域名区别?
二级域名是指位于主域名之下的域名层次。例如,如果
example.com
是一个主域名,那么sub.example.com
就是一个二级域名,其中sub就是在主域名前添加的一个层次。泛域名又称为泛解析,是指使用通配符*进行的DNS解析记录设置,它能够匹配所有的子域名。例> 如,设置
*.example.com
指向某个IP地址或主机名,这样任何以example.com
结尾的子域名请求都会被> 解析到同一目的地,不论是blog.example.com
、news.example.com
还是其他任意前缀的子域名。
Nginx的配置文件中,server_name
是一个指令,用于定义HTTP请求中的主机名(即Host头部)与特定的虚拟主机配置相匹配的规则。
当Nginx接收到一个HTTP请求时,它会根据请求中的Host头部信息去匹配server_name
配置,从而确定由哪个虚拟主机配置来处理这个请求。支持以下几种匹配方式:
-
精确匹配:直接指定确切的域名或IP地址,如
server_name example.com
。 -
通配符匹配:使用星号
*
作为通配符,匹配任意字符串,如server_name
*.example.com
或者example.*
。 -
正则表达式匹配:在域名前加上波浪线
~
或~*
(不区分大小写)来表示正则表达式匹配,如server_name ~^(www\.)?example\.com$
。~
:表示进行正则表达式匹配,并且是区分大小写的。^
:匹配字符串的开始。(www\.)?
:这是一个可选的匹配组,表示前面的www.可以出现0次或1次(由?定义)。.是对.的转义,因为.在正则表达式中是一个特殊字符,表示匹配任意单个字符,但在这里我们需要匹配实际的点字符.。example\.com
:精确匹配字符串example.com,.用于转义点号,使其匹配字面上的点字符。$
:匹配字符串的结束。
如果请求的Host头部值与任何
server_name
配置都不匹配,Nginx将使用默认的服务器块来处理请求,如果没有明确设置默认服务器块,则可能由第一个列出的服务器块处理。特殊值
_
(下划线)在server_name
中表示不匹配任何域名的请求,通常用于捕获未指定的Host头请求或作为默认的配置块(处理那些没有匹配到任何其他server_name
配置的请求)。
6.2、server_name匹配规则
Nginx的server_name匹配顺序遵循以下规则
- 精确匹配(
Exact Match
): 首先尝试精确匹配,即请求的Host
头部与配置中的server_name
完全一致。这是优先级最高的匹配方式。 - 前缀通配符匹配(
Prefix Wildcard Matching
): 接着尝试匹配以*
开头的最长通配符名称,如*.example.org
。如果有多个这样的匹配项,最长的前缀优先。 - 后缀通配符匹配(
Suffix Wildcard Matching
): 然后是匹配以*结尾的最长通配符名称,如mail.*
。如果有多个这样的匹配项,最长的后缀优先。 - 正则表达式匹配(
Regular Expression Matching
): 最后,如果上述都没有匹配到,Nginx
会按照配置文件中出现的顺序检查正则表达式匹配项,第一个匹配成功的正则表达式胜出。正则表达式以波浪线~开头,例如server_name ~ "^www\d+\.example\.net$"
。
如果没有任何server_name
匹配成功,Nginx
会使用默认的server
块处理请求,该块通常监听一个默认的端口(如80或443),并且可能带有default_server
或default_host
标记。
记住,当配置多个server_name
时,精确匹配始终优先,因此为了效率和清晰性,建议尽量使用精确匹配,并将精确匹配放在配置的前面。如果服务器配置了大量的域名或长域名列表,可能还需要调整server_names_hash_max_size
和server_names_hash_bucket_size
的值,以确保Nginx
可以正确启动并高效地处理请求。
注意:server_name
匹配分先后顺序,写在前面的匹配上后就不会继续往下匹配了。
6.2.1、精确匹配
-
单一域名
修改
C:\Windows\System32\drivers\etc
下的hosts文件配置
配置(单个站点)
[root@VM-16-14-centos conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name wts01.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
浏览器访问:http://wts01.com
-
配置(两个站点)
[root@VM-16-14-centos conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # 虚拟主机 vhost server { listen 80; # 域名、主机名 server_name wts01.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } # 虚拟主机 vhost server { listen 80; # 域名、主机名 server_name wts02.com; location / { root /www/vod; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
没有匹配到任何域名时,从上到下访问第一个Server站点 http://192.168.119.128/
精准匹配域名,访问wts01.com站点 浏览http://wts01.com
精准匹配域名,访问wts02.com站点 http://wts02.com
-
多域名
[root@VM-16-14-centos conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name wts01.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name wts02.com wts03.com; # 这里的域名都能能访问到vod站点 location / { root /www/vod; index index.html index.htm; } } }
wts02.com、wts03.com域名都访问到vod站点
6.2.2、通配符匹配
-
通配符开始匹配
server { listen 80; server_name test.qiuyl.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name *.wts02.com; # 通配符开始匹配,这里的域名都能能访问到vod站点 location / { root /www/vod; index index.html index.htm; } }
wts01.com为精确匹配访问www,其它为通配符匹配访问vod。
-
通配符结束匹配
server { listen 80; server_name wts01.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name wts.*; # 通配符结束匹配,这里的域名都能能访问到vod站点 location / { root /www/vod; index index.html index.htm; } }
wts开头域名访问vod站点
6.2.3、正则表达式匹配
-
正则匹配以
~
开头:在Nginx的server_name
指令中,当使用正则表达式来匹配域名时,需要以~
开头来指示这是一个区分大小写的正则匹配。如果要进行不区分大小写的匹配,则应使用~*
。 -
精确匹配与正则匹配:如果不使用
~
或~*
前缀,Nginx会将server_name
后面的值视为精确字符串匹配。 -
锚定符号
^
和$
:在正则表达式中,^
表示字符串的开始位置,$
表示字符串的结束位置。使用它们可以确保整个域名完全匹配指定的模式,而不是部分匹配。例如:~^www.example.com$会精确匹配"www.example.com",而不匹配像"subdomain.www.example.com"这样的子域名。
^hello$只会精确匹配整个字符串"hello",而不是像"hello there"或者"hi hello"这样的字符串。
-
点
.
的转义:在正则表达式中,.是一个特殊字符,代表任何单个字符(除了换行符)。如果你要匹配字面上的点.),需要使用反斜线\进行转义。 -
大括号
{}
的处理:在Nginx配置文件中,大括号{}有特殊的含义,用于定义指令块。因此,如果正则表达式中包含大括号,并且这些大括号不是用于量词(例如{2,3}),为了防止解析错误,应该将整个正则表达式用双引号包围。例如,server_name “~^(www\.)?example\.net(:[0-9]+)?$”; 这里的双引号使得大括号被正确识别为正则表达式的一部分,而不是Nginx的指令结构。-
正则表达式术语解释
匹配模式: ~* 表示不区分大小写的正则匹配。 !~ 表示区分大小写的正则不匹配。 !~* 表示不区分大小写的正则不匹配。 基本元字符: . 匹配任何单个字符(不包括换行符)。 \w 匹配字母、数字、下划线或汉字。 \s 匹配任何空白字符,如空格、制表符。 \d 匹配数字。 \b 匹配单词边界。 ^ 和 $ 分别匹配字符串的开始和结束。 量词: *, +, ? 分别表示前面元素可出现0次或多次、1次或多次、0次或1次。 {n}, {n,}, {n,m} 分别表示前面元素精确出现n次、至少n次、n到m次。 *?, +?, ??, {n,m}? 等懒惰量词,尽可能少地匹配。 特殊字符类: \W, \S, \D 分别匹配非字母数字下划线、非空白字符、非数字。 \B 匹配非单词边界。 字符组: [^x] 匹配除了x之外的任何字符。 [^abc] 匹配除了abc之外的任何字符。 匹配单个特定字符: [abc] 匹配'a'、'b' 或 'c' 中的任意一个字符。 范围匹配: [a-z] 匹配任何小写字母从'a'到'z'。 [0-9] 匹配任何数字从'0'到'9'。 [A-Za-z0-9] 匹配任何大小写字母或数字。 括号与捕获: (exp) 捕获表达式到自动编号的组中。 (?:exp) 非捕获组,用于分组但不捕获内容。 (?<name>exp) 或 (?'name'exp) 命名捕获组,通过名字引用捕获的内容。 预查断言: (?=exp) 零宽度正向先行断言,匹配exp前面的位置。 (?<=exp) 零宽度正向回顾断言,匹配exp后面的位置。 (?!exp) 零宽度负向先行断言,匹配后面不跟着exp的位置。 (?<!exp) 零宽度负向回顾断言,匹配前面不跟着exp的位置。 注释: (?#comment) 在正则表达式中添加注释,提高可读性。
-
配置
server { listen 80; server_name wts01.com; location / { root /www/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name ~^[0-9]+\.wts.com$; # 这里的域名都能访问到vod站点 location / { root /www/vod; index index.html index.htm; } }
浏览器访问:
-
7、反向代理
7.1、网关、反向、正向代理介绍
7.1.1、反向代理
概述
反向代理是代理到服务端
Nginx代理服务器接收来自互联网上用户的HTTP请求,并将这些请求转发给内部网络中的一个或多个服务器
。这些内部服务器通常是Web服务器,负责处理请求并生成响应。Nginx收到内部服务器的响应后,再将这些响应返回给最初的互联网用户。
在这个过程中,外部用户只与Nginx交互,对内部网络结构和实际处理请求的服务器并不直接感知。
应用场景
-
负载均衡:Nginx可以根据不同的策略(如轮询、最少连接数、哈希等)将请求分发到多个后端服务器,从而实现负载均衡,提高系统的处理能力和可用性。
-
隐藏内部架构:外部用户只能看到Nginx代理服务器的IP地址,内部服务器的详细信息和结构得以保护,增强了安全性。
-
SSL卸载:Nginx可以处理HTTPS请求的加密和解密,减轻后端服务器的负担,即在Nginx上完成SSL/TLS握手,然后以未加密的形式将请求转发给后端服务器。
-
缓存静态内容:Nginx可以缓存静态文件或响应结果,对于频繁请求且内容不变的数据,可以直接从缓存中快速提供,提升响应速度。
-
请求过滤与修改:Nginx可以作为一道屏障,根据规则过滤请求,比如拒绝某些IP的访问,或者修改请求头和内容再转发,实现更灵活的控制。
-
故障转移:当某个后端服务器不可用时,Nginx可以自动将流量重定向到其他健康服务器,保证服务连续性。
-
内容路由:基于URL路径、主机名或其他条件,Nginx可以将请求路由到不同的后端服务,实现复杂的微服务架构部署。
7.1.2、正向代理
概述
正向代理是代理到客户端
Nginx正向代理主要服务于客户端,帮助它们克服访问外部资源时遇到的种种障碍。
Nginx正向代理是指Nginx服务器作为客户端和目标服务器之间的中介,帮助客户端访问外部网络资源的过程。在这种配置下,客户端通常处于受限的网络环境中,不能直接访问目标服务器(例如,因防火墙限制、地理位置限制或需要身份验证的资源)。
比如:我们内部用户需要上网,不能直接通外网,需要通过正向代理服务器才能上网。
应用场景
-
访问控制:企业或组织可以利用正向代理实施访问策略,比如内容过滤、审计或限制对特定网站的访问。
-
身份隐藏:客户端的真实IP地址被代理服务器的IP所替代,有助于保护客户端的隐私。
-
突破网络限制:在存在网络限制的环境下,正向代理可以帮助用户访问原本无法直接访问的外部资源。
-
缓存和加速:正向代理还可以缓存经常访问的内容,减少网络延迟和带宽消耗。
7.1.3、网关
Nginx不仅仅是一个高性能的Web服务器,它还常被用作API网关。
比如,咱们家庭网络需要通外网,需要路由器转发出去,那这个路由器就是一个网关。和正向代理拓扑图一样,正向代理的代理服务器也是网关。
7.1.4、隧道式模型
Nginx代理模式非常明显,就是隧道式模型。简单点就是一进一出,所有请求都是经过该代理,所有该服务器的带宽决定了速度因素。
如何解决?
LVS(负载均衡器):通过DR模型,就是后端服务器返回的时候直接放回到客户端,不经过Nginx代理服务器。请求流程不变。
架构图
7.2、负载均衡策略
负载均衡:负载均衡分配,有效降低服务器压力。通过算法(轮询、IP哈希、随机)实现。
当出现我Nginx分配到的服务器上压力已经过满时,有个retry机制(重试机制)可以重新分配负载服务
7.2.1、配置反向代理
关键字:proxy_pass,该关键字后面的规则不会进行匹配了
语法:proxy_pass [主机、网址]或[一组服务器]
注意:不支持https的proxy_pass的,因为需要和域名证书扯上关系
-
配置文件,写了二级域名
[root@VM-16-14-centos nginx]# cat conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name wts01.com; location / { proxy_pass http://www.atguigu.com; # 这里二级域名写了www # root /www/www; # index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } [root@VM-16-14-centos nginx]# systemctl reload nginx
-
浏览器访问:http://192.168.119.128/
-
配置文件,不写二级域名
[root@VM-16-14-centos nginx]# cat conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name wts01.com; location / { proxy_pass http://atguigu.com; # root /www/www; # index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } [root@VM-16-14-centos nginx]# systemctl reload nginx
-
浏览器访问
可以看到浏览器的URL地址的变化,已经http://192.168.119.128(Nginx服务器)请求的状态码为302(临时重定向状态码),所有咱们浏览器URL地址会变化。
该重定向是可以关闭的。
7.2.2、负载均衡基本配置
安装Docker,启动两个Nginx容器,并修改默认的index.html文件。修改宿主机的nginx.conf文件来实现负载均衡的效果。
-
安装Docker:docker-ce安装教程-阿里巴巴开源镜像站
-
启动两个Nginx容器,并修改index.html文件
[root@localhost ~]# docker pull nginx [root@localhost ~]# docker run -dit --name web1 -p 81:80 nginx 00bce741b8a29c3ad68b861ed09239cb5f956746174650407fdb5f57d5030916 [root@VM-16-14-centos ~]# docker run -dit --name web2 -p 82:80 nginx 6643bbf0f2b8dea366f5b790dd2affed342c63a2b402afcd3738f1c34880f377 [root@localhost ~]# ll total 1056 -rw-------. 1 root root 1647 Jan 28 2021 anaconda-ks.cfg drwxr-xr-x 9 1001 1001 186 Apr 21 18:29 nginx-1.22.1 -rw-r--r-- 1 root root 1073948 Apr 21 17:59 nginx-1.22.1.tar.gz [root@VM-16-14-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6643bbf0f2b8 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:82->80/tcp, :::82->80/tcp web2 00bce741b8a2 nginx "/docker-entrypoint.…" 15 seconds ago Up 13 seconds 0.0.0.0:81->80/tcp, :::81->80/tcp web1 [root@localhost ~]# docker exec -it web1 bash root@00bce741b8a2:/# echo web1 > /usr/share/nginx/html/index.html root@00bce741b8a2:/# exit [root@localhost ~]# docker exec -it web2 bash root@6643bbf0f2b8:/# echo web2 > /usr/share/nginx/html/index.html root@6643bbf0f2b8:/# exit exit [root@localhost ~]# curl 127.0.0.1:81 web1 [root@localhost ~]# curl 127.0.0.1:82 web2
-
配置宿主机的nginx.conf文件,实现负载均衡
[root@localhost conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # 通过upstream和proxy_pass来实现负载均衡 upstream web { server localhost:81; server localhost:82; } server { listen 80; server_name wts01.com; location / { proxy_pass http://web; # 跳转到upstream区域中 # root /ww/qiuyl01; # index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } [root@localhost conf]# systemctl reload nginx
浏览器访问
每次刷新浏览器,可以看到不同的内容。对应到后端不同的机器(这里是容器)。
http://192.168.119.128/
7.2.3、负载均衡策略
默认采用轮询方式
1)、轮询
默认情况下使用轮询方式,逐一转发,这种方式适用于无状态请求。
2)、weight(权重)
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
upstream httpd {
server 127.0.0.1:8050 weight=10 down;
server 127.0.0.1:8060 weight=1;
server 127.0.0.1:8060 weight=1 backup;
}
- down:表示当前的server暂时不参与负载
- weight:默认为1.weight越大,负载的权重就越大。
- backup: 其它所有的非backup机器down或者忙的时候,请求backup机器
下列几种策略中down和backup不常用,因为加入策略时需要重新reload使配置更新(reload会使应用短时间内中断),这种手动效率不行出现意外情况不能第一时间处理。一般采用动态方式。
1)weight(权重)
应用场景:每台机器的配置可能不一,有的配置高,有的配置低。配置高的咱们需要多处理一些请求负载,于是就有了权重(weight)。
2)down(下线)
应用场景:down可以使某个负载均衡节点不参与负载均衡了
3)backup(备用服务器)
应用场景:其它负载节点实在是不可用了,才会使请求访问到标有backup的机器上。
3)、其它负责均衡策略
下列几种策略生产环境也都不会使用。主要原因是没法动态的上下限服务器,因为需要reload。一般使用 lua 脚本编程去管理动态上下线。
默认使用轮询的负载均衡策略,有个问题就是
不能保持会话
。
生产环境一般采用 lua 脚本、Token会话保持(配合轮询),来保持会话
-
ip_hash
根据客户端的ip地址转发同一台服务器,可以保持回话。已经不太适应现在这个移动互联网时代了。因为咱们手机客户端移动时IP是会动态变动的,有的时候信号是好是坏 IP 也会变化。所以这种方式不太合适。没法保持会话
-
least_conn
最少连接访问使后端会话连接数保持一个均衡。但是一般会话连接数比较少的原因是咱们给某台机器的权重比较低,所以连接少。而且也不适合保证服务的上下线
- 因为我们增加一台新的机器时,连接会话数最少,那么后面是不是所有的连接都会在这台机器上。
- 配置这个策略需要reload,reload的原理是需要将老的线程kill掉。所以咱们后端服务器的会话数都变为0了
-
url_hash
根据用户访问的url定向转发请求每个URL地址会被Nginx解析为一个hash值。我们知道注册、登录、首页的url地址是不一致的,如果登录后访问其它页面地址变化了那么url_hash值也会变化,有可能会转发在不同的服务器。
-
fair
根据后端服务器响应时间转发请求需要下载第三方插件,根据后端服务器的响应时间转发请求。也不合理。会出现流量倾斜的情况。因为有可能因为网络原因导致
8、Nginx动静分离
Nginx动静分离的原理主要是基于Nginx作为反向代理服务器的角色,利用其高效处理静态内容的能力,将网站的动态请求和静态请求分发到不同的后端服务器或处理器上,以此来优化资源的加载速度和提升整个系统的性能。
具体来说,动静分离的工作机制包含以下几个关键点:
- URL匹配:Nginx通过配置文件中的location指令对客户端的请求URL进行匹配。可以根据文件扩展名或者路径前缀来区分静态资源请求和动态资源请求。
- 静态内容直接处理:当Nginx识别出请求的是静态资源(如HTML、CSS、JavaScript、图片等),它会直接从静态文件存储位置(通常是本地文件系统或者配置的缓存目录)读取并返回给客户端,而无需将请求转发给后端的应用服务器(如Tomcat、Apache等)。Nginx处理静态内容的效率非常高,能显著减少延迟。
- 动态内容转发:对于动态内容请求(如PHP、JSP等脚本生成的页面),Nginx则将其转发(代理Pass)到后端的应用服务器进行处理。处理完成后,应用服务器将结果返回给Nginx,Nginx再将响应转发给客户端。
- 负载均衡:在动静分离的同时,Nginx还可以作为负载均衡器,根据设定的策略将动态请求分发到多个应用服务器,以进一步提高系统的可用性和扩展性。
- 缓存策略:Nginx还可以配置缓存策略,对频繁访问的静态资源进行缓存,减少对后端存储的访问,提高响应速度。
比如,咱们接下来要做的案例是:
将静态资源存放在Nginx侧,动态资源存放在Tomcat服务器侧。静态资源通过Nginx的location指令来实现路径匹配,其它请求路径都将在Tomcat服务器侧处理。
8.1、Docker部署Tomcat
[root@localhost ~]# docker pull billygoo/tomcat8-jdk8
[root@localhost ~]# docker run -dit --name tomcat81 -p 8081:8080 billygoo/tomcat8-jdk8
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f67fc50b3725 billygoo/tomcat8-jdk8 "catalina.sh run" 2 weeks ago Up 25 minutes 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat81
浏览器访问:http://192.168.119.128:8081/
8.2、准备项目
charts-project.zip下载地址:https://pan.baidu.com/s/1baD910BQD1DGdwdMmK0qTg?pwd=aaaa
8.3、部署项目
将项目上传到宿主机并复制到容器中
[root@localhost ~]# ll
drwxr-xr-x 6 root root 124 4月 30 2022 charts-project
-rw-r--r-- 1 root root 858274 8月 16 09:49 charts-project.zip
[root@localhost ~]# docker cp charts-project/ tomcat81:/usr/local/tomcat
Successfully copied 1.5MB to tomcat81:/usr/local/tomcat
进入Tomcat容器将项目文件cp到webapps/ROOT目录下
[root@localhost ~]# docker exec -it tomcat81 bash
root@f67fc50b3725:/usr/local/tomcat# cp -rf charts-project/* webapps/ROOT/
浏览器访问:http://192.168.119.128:8081/
接着这里我们可以打开浏览器开发者模式,可以看到我们主页面的静态资源文件(css、js)路径保存位置,一般都是相对路径。所以我们只需要将这里访问的静态资源地址,代理到访问Nginx的静态资源地址即可。
8.4、配置动静分离
将Tomcat容器中charts项目的静态资源目录删除或重命名
root@f67fc50b3725:/usr/local/tomcat# cd webapps/ROOT
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# ls
01-$(this).index()╦ў╥¤╬╩╠т.html WEB-INF bg-button.png bg-nav-item.png bg-upper.png favicon.ico images index.jsp tomcat-power.gif tomcat.gif tomcat.svg
RELEASE-NOTES.txt asf-logo-wide.svg bg-middle.png bg-nav.png css fonts index.html js tomcat.css tomcat.png
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# mv js js.bak
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# mv images/ images.bak
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# mv fonts fonts.bak
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# mv css/ css.bak
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT#
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT#
root@f67fc50b3725:/usr/local/tomcat/webapps/ROOT# ls -al
total 208
drwxr-xr-x 1 root root 140 Aug 16 02:01 .
drwxr-xr-x 1 root root 18 Jun 29 2018 ..
-rw-r--r-- 1 root root 527 Aug 16 01:53 01-$(this).index()╦ў╥¤╬╩╠т.html
-rw-r--r-- 1 root root 6794 Jun 29 2018 RELEASE-NOTES.txt
drwxr-xr-x 2 root root 21 Jul 31 2018 WEB-INF
-rw-r--r-- 1 root root 27235 Jun 29 2018 asf-logo-wide.svg
-rw-r--r-- 1 root root 713 Jun 29 2018 bg-button.png
-rw-r--r-- 1 root root 1918 Jun 29 2018 bg-middle.png
-rw-r--r-- 1 root root 1392 Jun 29 2018 bg-nav-item.png
-rw-r--r-- 1 root root 1401 Jun 29 2018 bg-nav.png
-rw-r--r-- 1 root root 3103 Jun 29 2018 bg-upper.png
drwxr-xr-x 2 root root 23 Aug 16 01:53 css.bak
-rw-r--r-- 1 root root 21630 Jun 29 2018 favicon.ico
drwxr-xr-x 2 root root 102 Aug 16 01:53 fonts.bak
drwxr-xr-x 2 root root 104 Aug 16 01:53 images.bak
-rw-r--r-- 1 root root 14248 Aug 16 01:53 index.html
-rw-r--r-- 1 root root 12290 Jun 29 2018 index.jsp
drwxr-xr-x 2 root root 84 Aug 16 01:53 js.bak
-rw-r--r-- 1 root root 2376 Jun 29 2018 tomcat-power.gif
-rw-r--r-- 1 root root 5581 Jun 29 2018 tomcat.css
-rw-r--r-- 1 root root 2066 Jun 29 2018 tomcat.gif
-rw-r--r-- 1 root root 5103 Jun 29 2018 tomcat.png
-rw-r--r-- 1 root root 67795 Jun 29 2018 tomcat.svg
浏览器访问,可以看到目前页面没有任何图片或样式
在宿主机侧,将charts-project项目的css、js、images、fonts目录cp到Nginx的静态目录(Nginx根目录)中
[root@localhost ~]# cd charts-project
[root@localhost charts-project]# ls
01-$(this).index()╦ў╥¤╬╩╠т.html css fonts images index.html js
[root@localhost charts-project]# cp -r css /usr/local/nginx/html
[root@localhost charts-project]# cp -r js /usr/local/nginx/html
[root@localhost charts-project]# cp -r images /usr/local/nginx/html
[root@localhost charts-project]# cp -r fonts /usr/local/nginx/html
[root@localhost charts-project]# cd /usr/local/nginx/html
[root@localhost html]# ls
50x.html css fonts images index.html js
8.4.1、配置nginx.conf
目的:只要请求是静态资源(js、images、css、fonts)的都会在Nginx的root指令指定的目录查找,而不是去Tomcat服务器端查找
[root@localhost conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream web {
server 192.168.119.128:8081;
#server 192.168.119.128:8082;
#server 192.168.119.128:8083;
}
# 虚拟主机 vhost
server {
listen 80;
# 域名、主机名
server_name wts01.com;
location / {
proxy_pass http://web;
#root /www/www;
#index index.html index.htm;
}
location /images {
root html;
index index.html index.htm;
}
location /js {
root html;
index index.html index.htm;
}
location /css {
root html;
index index.html index.htm;
}
location /fonts {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
浏览器访问,可以看到本地资源也是正常访问到的,页面也正常显示
8.4.2、使用正则配置动静分离
这里有个问题:这样去写location可能导致location比较多
Nginx配置里面的正则:区分大小写的正则~
开头,不区分大小写的正则~*
开头
(js|img|css)
:| 符号表示或者,这里意思就是js、img、css三个目录都能匹配到
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream web {
server 192.168.119.128:8081;
#server 192.168.119.128:8082;
#server 192.168.119.128:8083;
}
# 虚拟主机 vhost
server {
listen 80;
# 域名、主机名
server_name wts01.com;
location / {
proxy_pass http://web;
#root /www/www;
#index index.html index.htm;
}
location ~*/(js|css|fonts|images) {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
【拓展】
常见的Nginx正则表达式
^ :匹配输入字符串的起始位置
$ :匹配输入字符串的结束位置
* :匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”
+ :匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o”
? :匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效于”{0,1}”
. :匹配除“\n”之外的任何单个字符,若要匹配包括“\n”在内的任意字符,请使用诸如“[.\n]”之类的模式
\ :将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如“\n”匹配一个换行符,而“\$”则匹配“$”
\d :匹配纯数字
{n} :重复 n 次
{n,} :重复 n 次或更多次
{n,m} :重复 n 到 m 次
[] :定义匹配的字符范围
[c] :匹配单个字符 c
[a-z] :匹配 a-z 小写字母的任意一个
[a-zA-Z0-9] :匹配所有大小写字母或数字
() :表达式的开始和结束位置
| :或运算符 //例(js|img|css)
location正则:
//location大致可以分为三类
精准匹配:location = /{}
一般匹配:location /{}
正则匹配:location ~/{}
//location常用的匹配规则:
= :进行普通字符精确匹配,也就是完全匹配。
^~ :表示前缀字符串匹配(不是正则匹配,需要使用字符串),如果匹配成功,则不再匹配其它 location。
~ :区分大小写的匹配(需要使用正则表达式)。
~* :不区分大小写的匹配(需要使用正则表达式)。
!~ :区分大小写的匹配取非(需要使用正则表达式)。
!~* :不区分大小写的匹配取非(需要使用正则表达式)。
//优先级
首先精确匹配 =
其次前缀匹配 ^~
其次是按文件中顺序的正则匹配 ~或~*
然后匹配不带任何修饰的前缀匹配
最后是交给 / 通用匹配
注意:
- 精确匹配: = , 后面的表达式中写的是纯字符串
- 字符串匹配: ^~ 和 无符号匹配 , 后面的表达式中写的是纯字符串
- 正则匹配: ~ 和 ~* 和 !~ 和 !~* , 后面的表达式中写的是正则表达式
location的说明
(1)location = / {}
=为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。若 location /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/。
(2)location / {}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
但若后面是正则表达式会和最长字符串优先匹配(最长匹配)
(3)location /documents/ {}
匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
(4)location /documents/abc {}
匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
(5)location ^~ /images/ {}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
(6)location ~* \.(gif|jpg|jpeg)$ {}
匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则
(7)location /images/abc {}
最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在
(8)location ~ /images/abc {}
匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条
(9)location /images/abc/1.html {}
匹配/images/abc/1.html 文件,如果和正则 ~ /images/abc/1.html 相比,正则优先级更高
优先级总结:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (location /)
实际网站使用中,至少有三个匹配规则定义:
-
第一个必选规则
直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。这里是直接转发给后端应用服务器了,也可以是一个静态首页location = / { proxy_pass http://127.0.0.1:8080/; }
-
第二个必选规则
处理静态文件请求,这是nginx作为http服务器的强项,有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用location ^~ /static/ { root /webroot/static/; } location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; }
-
第三个规则
通用规则,用来转发动态请求到后端应用服务器location /api/ { proxy_pass http://127.0.0.1:3000/api/ }
9、URLRewrite伪静态配置
9.1、简介
1、Nginx的rewrite
语法主要用于实现URL重写和重定向功能,它是ngx_http_rewrite_module
模块的一部分,该模块默认包含在Nginx中。以下是rewrite
指令的基本语法结构和一些关键点:
格式:
rewrite regex replacement [flag];
regex
: 是一个正则表达式,用于匹配请求的URI部分。replacement
: 是一个字符串,用于替换匹配到的部分。flag
(可选): 控制重写操作的行为,常见的flag包括:- last: 表示完成当前的重写规则后,继续向下搜索并尝试匹配其他location块。
- break: 如果当前重写规则匹配并执行后,停止执行当前的rewrite指令序列,并不再进行后续的rewrite规则匹配,不影响其它指令匹配。
- redirect: 返回临时重定向状态码(默认为302),告诉客户端使用新的URL。
- permanent: 返回永久重定向状态码(301),适合永久性的URL变更。
其他高级用法还包括使用条件语句
if
来控制rewrite
的执行,以及使用变量等。例如,可以在server
或location
上下文中使用if
来判断特定条件,然后基于这些条件应用重写规则。
2、rewrite指令和server_name指令使用正则表达式时,其语法和要求是不一样的?
-
rewrite指令:
- 默认匹配行为:在rewrite指令中,正则表达式默认就是按正则模式进行匹配的,无需在正则前加上特殊字符来表明这是一个正则表达式。Nginx会自动识别并处理正则匹配逻辑。
- 正则指示:尽管不是强制的,但你可以使用
~
(区分大小写)或~*
(不区分大小写)来显式指定正则匹配的类型,这在需要强调匹配特性时很有用,但不是必需的。
-
server_name指令:
- 默认匹配行为:默认情况下,server_name指令支持精确匹配和使用通配符(如*.example.com),而不是正则表达式。为了启用正则匹配,必须明确指定。
- 正则指示:使用正则表达式时,必须在正则前加上
~
(区分大小写)或~*
(不区分大小写)来明确告知Nginx这是一个正则匹配模式。没有这些前缀,字符串将被视为精确匹配或通配符匹配。
一句话总结:
rewrite
指令默认接受正则表达式且不强制要求特殊前缀,而server_name
指令要使用正则表达式必须明确通过~
或~*
来指示,因为其默认处理非正则类型的匹配。
9.2、Rewrite的优缺点?
-
优点:掩藏真实的url以及url中可能暴露的参数,以及隐藏web使用的编程语言,提高安全性便于搜索引擎收录
-
缺点:降低效率,影响性能。如果项目是内网使用,比如公司内部软件,则没有必要配置。
9.3、实例
9.3.1、场景1
下列配置 rewrite ^/test.html$ /index.html?testParam=3 break;
意思是,只要访问了/test.html
,那么就相当于访问的/index.html?testParam=3
路径,有助于隐藏传入的参数和SEO优化
[root@localhost conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream web {
server 192.168.119.128:8081;
#server 192.168.119.128:8082;
#server 192.168.119.128:8083;
}
# 虚拟主机 vhost
server {
listen 80;
# 域名、主机名
server_name wts01.com;
location / {
rewrite ^/test.html$ /index.html?testParam=3 break; # 重写URL
#root /www/www;
#index index.html index.htm;
}
location ~*/(js|css|fonts|images) {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
浏览器访问路径对比
可以看到访问/test.html
路径,和访问/index.html?testParam=3
路径效果一致,实现了我们隐藏传入的参数和SEO优化的目的
访问:http://192.168.119.128/test.html
访问:http://192.168.119.128//index.html?testParam=3
9.3.2、场景2
咱们一般网页翻页时,需要传入对应参数,比如/index,jsp?pageNum=0、/index,jsp?pageNum=25、/index,jsp?pageNum=50
我们可以通过rewrite
实现访问对应数字来实现翻页效果,如下指令。
rewrite 翻页效果指令:rewrite ^/([0-9]+).html$ /index,jsp?pageNum=$1 break;
在 Nginx 的 rewrite 指令中,$1
表示正则表达式中捕获的第一个匹配组。在你提供的规则中,正则表达式 ^/([0-9]+).html$ 匹配以数字开头,以 “.html” 结尾的 URI。
^
表示匹配字符串的开始。([0-9]+)
是一个捕获组,表示匹配一个或多个数字。\.html$
表示匹配以 “.html” 结尾的字符串。()
内的部分就是捕获组,在这里用来捕获数字。
如果请求的 URI 符合这个规则,$1
就会被捕获的数字替换,然后将请求重写为 /index.jsp?pageNum=捕获的数字
。这样就实现了将类似 http://example.com/123.html
这样的 URI 重写为 http://example.com/index.jsp?pageNum=123
。
10、防盗链配置
防盗链本质是存在服务器上的资源只能由服务器本身进行访问,其他引用的资源不能访问
10.1、如何实现?
浏览器的第二次请求可以看到Referer数据来源,在Request Headers里面是有Referer,表示之前第一次页面的资源是从这里过来的,后续的资源也将从这里获取。
所以,我们可以根据判断该Referer值来判断是否具有访问权限。
10.2、操作案例
准备两台机器,第一台机器能正常访问自己网站。第二台机器配置反向代理到第一台机器,配置防盗链后不能访问网站
主机IP | 备注 |
---|---|
192.168.119.128 | 首先通过容器部署Tomcat,其次通过Nginx代理到自身的8081上(在之前Nginx篇章有介绍) |
192.168.119.129 | Nginx代理到192.168.119.128主机上 |
1)192.168.119.128(第一台主机)
站点环境
[root@localhost conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f67fc50b3725 billygoo/tomcat8-jdk8 "catalina.sh run" 2 weeks ago Up 3 hours 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat81
配置
[root@localhost conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.119.128:8081; # 代理到容器部署的Tomcat
}
location ~*/(js|css|fonts|images) {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
[root@localhost nginx]# systemctl reload nginx
浏览器访问
2)192.168.119.129(第二台主机)配置
[root@localhost conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.119.128; # 代理到第一台主机
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
[root@localhost nginx]# systemctl reload nginx
浏览器访问
10.3、防盗链配置
Nginx 的 valid_referers
指令用于检查HTTP
请求中的Referer
头信息,以确定请求是否源自允许的来源。这个指令可以帮助实施防盗链策略,保护网站资源不被未经授权的第三方网站直接链接。
valid_referers [none|blocked|server_names|string ...];
参数说明:
none
: 表示请求没有Referer头信息blocked
: 表示Referer头信息被防火墙或代理服务器屏蔽或修改server_names
: 一个或多个主机名,可以是具体的域名或者IP地址,也可以使用通配符 *。如:valid_referers none server_names example.com *.example.org;string
: 允许直接指定一个字符串作为合法的referer值进行匹配,也可以是正则表达式(需使用~*
或~
前缀来标记)
10.3.1、防盗链配置解释
valid_referers 192.168.119.128;
if ($invalid_referer) { # 注意这里if后要加空格
return 403; # 返回错误码403
}
valid_referers 192.168.119.128;
这一行指定了被认为是合法(valid)的referer来源。在这个例子中,只有当请求是从192.168.119.128这个IP地址发起的,才被视为合法的referer。你可以添加多个IP或域名,用空格分隔,例如 valid_referers 192.168.119.128 example.com;。if ($invalid_referer)
{ 这里使用了一个条件判断语句,$invalid_referer
是一个内部变量,由Nginx自动设置。当请求的referer头不符合valid_referers列表中的任何一个时,$invalid_referer
会被设置为一个非空值,表示这是一个无效的referer。return 403;
当$invalid_referer
为真,即请求的referer不在允许的列表内时(浏览器侧),Nginx会返回HTTP状态码403(Forbidden),意味着服务器理解客户端的请求,但是拒绝执行此请求。这通常用于阻止未经授权的外部网站直接链接到你的资源,保护你的带宽和内容免遭盗用。
一句话总结:这段配置的作用是检查HTTP请求头中的Referer字段,如果请求不是从指定的IP地址(在这个例子中是192.168.119.128)发起的,则拒绝该请求,返回403 Forbidden错误。
10.3.2、配置nginx.conf
只有valid_referers列表中地址,才能访问静态数据
[root@localhost nginx]# cat conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.119.128:8081;
}
location ~*/(js|css|fonts|images) {
valid_referers 192.168.119.128;
if ($invalid_referer) { # 注意这里if后要加空格
return 403; # 返回错误码403
}
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
10.3.3、浏览器访问
第一台主机,可以看到第一台主机的数据来源是http://192.168.119.128
第二台主机,可以看到由于第一台主机配置防盗链之后,所有样式都无法访问
10.3.4、none配置
如果上面配置后,不但引用访问不能访问,直接访问站点资源也是不行的。如果需要直接访问可行,需要配置none
配置none
location ~*/(js|css|fonts|images) {
valid_referers none 192.168.200.7;
if ($invalid_referer) { # 注意这里if后要加空格
return 403; ## 返回错误码
}
root html;
index index.html index.htm;
}
直接访问静态资源图片
10.4、Curl工具测试
-I
表示:只获取HTTP头部信息
[root@localhost nginx]# curl -I 192.168.119.128/images/bg.jpg
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Sat, 17 Aug 2024 06:01:11 GMT
Content-Type: image/jpeg
Content-Length: 519806
Last-Modified: Fri, 16 Aug 2024 02:10:16 GMT
Connection: keep-alive
ETag: "66beb508-7ee7e"
Accept-Ranges: bytes
-e
表示:设置HTTP请求中的Referer头字段,可用于测试防盗链
[root@localhost nginx]# curl -e "https://wts01.com" -I 192.168.119.128/images/bg.jpg
HTTP/1.1 403 Forbidden
Server: nginx/1.20.2
Date: Sat, 17 Aug 2024 06:02:55 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
10.5、防盗链资源返回页面或图片
10.5.1、盗链返回页面
[root@localhost html]# cat ../conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.119.128:8081;
}
location ~*/(js|css|fonts|images) {
valid_referers 192.168.119.128;
if ($invalid_referer) { # 注意这里if后要加空格
return 403; ## 返回错误码
}
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
error_page 403 /40x.html; # 如果状态码返回为403,则跳转至40x.html文件页面
location = /40x.html {
root html;
}
}
}
在html文件目录创建40x.html
[root@localhost html]# cat 40x.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Error</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>An error occurred.</h1>
<p>非法访问.</p>
<p>If you are the system administrator of this resource then you should check
the error log for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>
浏览器访问
10.5.2、盗链返回图片
注意:需要提前准备好x.png
图片,并上传至/usr/local/nginx/html/images
目录(根据自身环境而定)
location ~*/(js|css|fonts|images) {
valid_referers 192.168.119.128;
if ($invalid_referer) {
rewrite ^/ /images/x.png break; # 匹配所有路径,跳转到x.png图片
# return 403; ## 返回错误码
}
root html;
index index.html index.htm;
}
浏览器访问
11、Keepalived高可用
11.1、介绍
Keepalived是一个开源的高可用性(HA, High Availability)解决方案,主要设计用于实现服务器的故障切换(failover)。它通过VRRP协议(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)来实现这一目标,从而保证关键服务的不间断运行。Keepalived不仅能够监测服务器健康状态,还能管理IP地址的虚拟浮动,确保在主服务器发生故障时,备份服务器能够无缝接管服务,提高服务的稳定性和可靠性。
核心功能包括:
高可用性(HA)
: Keepalived通过VRRP提供高可用性服务,可以配置为主机(MASTER)和备份主机(BACKUP)角色。当主服务器出现故障时,备份服务器会自动接管VIP(虚拟IP地址)及相关服务,实现无中断切换。健康检查
: Keepalived能够定期对服务器上的服务或系统状态进行健康检查,如检查HTTP服务、TCP端口、脚本执行结果等,确保服务正常运行。负载均衡
: 虽然Keepalived最初不是专门作为负载均衡器设计的,但其VRRP功能可以与LVS(Linux Virtual Server,Linux虚拟服务器)集成,实现基于IP层或内容请求的负载均衡,进一步提升系统的扩展性和可靠性。配置灵活性
: Keepalived使用配置文件(通常是/etc/keepalived/keepalived.conf)来定义VRRP实例、优先级、通告间隔、健康检查脚本等,便于管理和调整。通知机制
: 在状态变化时,Keepalived可以通过电子邮件、SNMP陷阱等方式通知管理员,以便及时了解系统状态。
总的来说,Keepalived是构建高度可靠互联网服务架构的关键组件,广泛应用于Web服务器、数据库服务、邮件服务等需要持续运行的关键业务场景中。
keepalived官网:http://www.keepalived.org
keepalived服务的三个重要功能:
- 管理LVS负载均衡软件
- 实现LVS集群节点的健康检查中
- 作为系统网络服务的高可用性(failover)
11.2、架构图
首先需要准备两台一样的Nginx代理服务器,从而代理到后端的服务。
我们不可能将某个单独的Nginx代理服务器的IP提供给用户访问,因为一旦某个Nginx代理出现问题不能及时处理。所以需要让用户通过访问VIP的方式来提供代理服务。
如果后端Nginx代理或者Keepalived出现故障那么VIP也会随之漂移到从节点,图中也就是Nginx02,从而保障Nginx代理服务器的高可用,而用户侧无感知。
Nginx01+Keepalived01出现故障VIP自动漂移到Nginx02+Keeplived02节点上,从而保障高可用性
下面,就来具体实现上图的功能
11.3、配置Nginx
配置nginx.conf(两台主机)
[root@localhost conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
第一台主机,编辑index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>
Host01 IP:192.168.119.128
</p>
</body>
</html>
第二台主机,编辑index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>
Host02 IP:192.168.119.129
</p>
</body>
</html>
11.4、配置Keepalived
1)安装Keepalived(两台主机)
yum install -y keepalived
2)配置keepalived.conf
配置第一台主机
这里只做keepalived最基本配置
[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_7
}
vrrp_instance VI_7 {
state MASTER
interface ens33
virtual_router_id 51
priority 100 # 优先级高于从
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.119.254
}
}
# 启动
[root@localhost]# systemctl start keepalived
配置第二台主机
[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
}
vrrp_instance VI_10 {
state MASTER
interface ens33
virtual_router_id 51
priority 50 # 优先级低于主
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.119.254
}
}
# 启动
[root@localhost]# systemctl start keepalived
由于,咱们将第一台主机作为keepalived的Master,他的优先级要高于第二台主机,所有只要第一台keepalived服务存活那么VIP就会在该节点
[root@localhost ~]# ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.119.128/24 brd 192.168.119.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.119.254/32 scope global ens33
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
访问VIP,由于VIP节点在第一台主机上,那么访问的也将是第一台主机
访问第一台主机
访问第二台主机
将第一台主机的Keepalived停止后,可以看见咱们的VIP已经切换
# 将第一台主机的Keepalived停止
[root@localhost ~]# systemctl stop keepalived
在第二台主机上查看ip
[root@localhost sbin]# ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.119.129/24 brd 192.168.119.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.119.254/32 scope global ens33
valid_lft forever preferred_lft forever
访问到第二台主机Nginx代理
11.5、编写脚本检查Nginx状态
上面,我们是通过默认的Keeplived的健康检查Keeplived服务状态,来实现VIP切换的。
那么,如果我们Nginx服务故障了而Keeplived服务没有故障,那么我们VIP是不会进行切换的,这个时候我们可以通过编写脚本的方式实现检查Nginx服务状态来判定VIP是否切换。
12、Https证书配置
12.1、防火墙的作用:
- 过滤进出网络的数据
- 管理进出访问网络的行为(限制他人进入内部网络,过滤掉不安全服务和非法用户)
- 封堵某些禁止业务(不让你看的网站你看不了)
- 记录通过防火墙信息内容和活动(你看了啥网站,传送了啥文件都有记录)
- 对网络攻击检测和告警
防火墙不能保护在网络传输中的数据,而HTTP 又是明文传输,HTTPS应运而生。
12.2、HTTP与HTTPS
HTTP(Hyper Text Transfer Protocol)协议是超文本传输协议的缩写,它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。HTTP有多个版本,目前广泛使用的是HTTP/1.1版本。
HTTP 默认工作在 TCP 协议 80 端口,用户访问网站 http:// 打头的都是标准 HTTP 服务。
HTTP 协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息。
一般http中存在如下问题:容易被窃取篡改冒充
请求信息明文传输,容易被窃听截取。
数据的完整性未校验,容易被篡改。
没有验证对方身份,存在冒充危险。
HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。HTTPS 默认工作在 TCP 协议443端口。
12.3、HTTP 与 HTTPS 区别
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。
12.4、对称加密与非对称加密
- 对称加密:使用相同的密匙对数据进行加密和解密。
- 非对称加密:加密和解密使用的不是同一把密钥。
公钥加密数据,私钥可以解密;
私钥加密数据,公钥可以解密。
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
12.5、使用阿里云配置https
阿里云免费证书购买在如下位置:
购买完成后在如下位置创建证书并申请证书:
填写验证信息
DNS对应的记录在如下页面:
证书签发后,选择下载:
下载后的文件如图所示:
接下来需要将这两个文件上传到nginx目录下的conf目录下:
nginx配置证书:
server {
listen 443 ssl;
server_name localhost; # 接收所有访问443端口的请求
ssl_certificate 7706851_www.xzj520520.cn.pem;
ssl_certificate_key 7706851_www.xzj520520.cn.key;
}
配置完之后,重启nginx
systemctl restart nginx
由于http协议默认的端口是80,而https默认的端口是443,如果想让http的访问跳转到https的访问,可以做如下配置:
server {
listen 80;
server_name www.xzj520520.cn xzj520520.cn; # 换成自己的域名
...
return 301 https://$server_name$request_uri;
}
至此,已经完成https的配置。
12.6、实战
配置nginx.concfig
user www www;
worker_processes auto;
error_log /www/wwwlogs/nginx_error.log crit;
pid /www/server/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;
events
{
use epoll;
worker_connections 51200;
multi_accept on;
}
http
{
include mime.types;
include proxy.conf;
default_type application/octet-stream;
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server_tokens off;
access_log off;
server {
listen 443 ssl;
server_name localhost;
ssl_certificate 7706851_www.xzj520520.cn.pem;
ssl_certificate_key 7706851_www.xzj520520.cn.key;
#配置根目录以及默认页面
location / {
root html;
index index.html index.htm index.php;
}
#出错页面配置
error_page 500 502 503 504 /50x.html;
#/50x.html文件所在位置
location = /50x.html {
root html;
}
}
server {
listen 80;
# server_name localhost www.xzj520520.cn xzj520520.cn;
server_name www.xzj520520.cn xzj520520.cn;
# 重定向,会显示跳转的地址server_name,如果访问的地址没有匹配会默认使用第一个,即www.xzj520520.cn
return 301 https://$server_name$request_uri;
}
}
访问http://xzj520520.cn, 发现自动变成https访问
访问https://a.xzj520520.cn,显示安全提示页面