Nginx_基础篇
- (一)、Nginx 简介
- 1.背景介绍
- (1).http和三大邮局协议
- (2).反向代理与正向代理
- 2.常见服务器对比
- (1).公司介绍
- (2).lls 服务器
- (3).Tomcat 服务器
- (4).Apache 服务器
- (5).Lighttpd 服务器
- (6).其他的服务器
- 3.Nginx的优点
- (1).速度更快、并发更高
- (2).配置简单,扩展性强
- (3).高可靠性
- (4).热部署
- (5).成本低、BSD许可证
- 4.Nginx的功能特性及常用功能
- (1).基本HTTP服务
- (2).高级HTTP服务
- (3).邮件服务
- (4).Nginx常用的功能模块
- (二)、Nginx 环境准备
- 1.Nginx版本介绍
- 2.准备服务器系统
- (1).环境准备
- 3.Nginx安装方式介绍
- (1).通过Nginx源码安装
- (2).Nginx的源码简单安装 (第一种)
- (3).Nginx的yum安装 (第二种)
- (4).源码简单安装和yum安装的差异:
- (5).查看nginx的目录
- (6).Nginx的源码复杂安装 (第三种)
- (7).Nginx删除的三步走
- 4. Nginx目录结构分析
- (1).安装我们的tree工具
- (2).Nginx的目录结构
- 5. Nginx服务器的启停命令
- (1).方式一:Nginx服务的信号控制
- (2).方式2: Nginx的命令行控制
- 6.Nginx服务器版本升级和新增模块
- (1).需求提出
- (2).环境准备
- (3).使用Nginx服务信号进行升级 (方案一)
- (4).使用Nginx安装目录的make命令完成升级 (方案二)
- (三)、Nginx核心配置文件结构
- 1.全局块
- (1).user指令
- (2).work process指令
- (3).其他指令
- 2.events块
- (1).events指令配置实列
- 3.http块
- (1).定义MIME-Type
- (2).自定义服务日志
- (3).其他配置指令
- 4.server块和location块
- (四)、Nginx进阶篇
- 1.Nginx服务器基础配置
- (1).需求提出
- (2).环境搭建
- (3).测试需求
- 2.Nginx服务操作的问题
- (1). Nginx配置成系统服务
- (2).Nginx命令配置到系统环境
- (三)、Nginx静态资源部署
- 1.Nginx静态资源概述
- 2.Nginx静态资源的配置指令
- (1).listen指令
- (2).server_name指令
- (3).匹配执行顺序
- (4).location指令
- (5).设置请求资源的目录root / alias
- (6).index指令 (指定默认在哪)
- (7).error_page指令
- 3.静态资源优化配置语法
- (1).sendfile,用来==开启高效的文件传输模式==。
- (2).==tcp_nopush==:该指令必须在==sendfile打开的状态==下才会生效,主要是用来提升网络包的**传输'效率'**
- (3).==tcp_nodelay==:该指令必须在==keep-alive连接开启==的情况下才生效,来提高网络包**传输的'实时性'**
- 4.Nginx静态资源压缩实战
- (1).Gzip模块配置指令
- (2).Gzip压缩功能的实例配置
- (3).Gzip和sendfile共存问题 (测试压缩成功✅)
- 5.静态资源的缓存处理
- (1).什么是缓存
- (2).什么是web缓存
- (3).web缓存的种类
- (4).浏览器缓存
- (5).为什么要用浏览器缓存
- (6).浏览器缓存的执行流程
- (7).浏览器缓存相关指令
- 6.Nginx的跨域问题解决
- (1).同源策略
- (2).跨域问题
- (3).跨域问题的案例演示
- (4).解决跨域问题的具体实现
- 7.静态资源防盗链
- (1).什么是资源盗链
- (2).Nginx防盗链的实现原理:
- (3).针对静态资源目录进行防盗链
- 8.Rewrite功能配置
- (1)."地址重写"与"地址转发"
- (2).set指令
- (3).Rewrite常用全局变量
- (4).if指令
- (5).break指令
- (6).return指令
- (7).rewrite指令
- (8).rewrite_log指令
- 9.Rewrite的案列
- (1).域名跳转
- (2).域名镜像
- (3).独立域名
- (4).目录自动添加"/"
- (5).合并目录
- (6).防盗链
- (四)、Nginx反向代理
- 1.Nginx反向代理概述
- 2.Nginx反向代理的配置语法
- (1).proxy_pass
- (2).proxy_set_header
- (3).proxy_redirect
- 3.Nginx反向代理实战
- (1).代理的服务器内容不同
- (2).代理的服务器内容相同
- 4.Nginx的安全控制
- (1).如何使用SSL对流量进行加密
- (2).nginx添加SSL的支持
- (3).Nginx的SSL相关指令
- (4).生产证书
- (5).开启SSL实列
- (6).将指定项目设置成https
- 5.反向代理系统调优
- (1).Proxy Buffer相关指令
(一)、Nginx 简介
1.背景介绍
Nginx(“engine x”)一个具有高性能的【HTTP】和【反向代理】的【WEB服务器】,同时也是一个【POP3/SMTP/IMAP代理服务器】,是由伊戈尔·赛索耶夫
(俄罗斯人)使用C语言编写的,Nginx的第一个版本是2004年10月4号发布的0.1.0版本
。另外值得一提的是伊戈尔·赛索耶夫将Nginx的源码进行了开源,这也为Nginx的发展提供了良好的保障。
(1).http和三大邮局协议
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也可以作为电子邮件代理服务器。
(2).反向代理与正向代理
- 正向代理
正常情况下,我们是直接通过http直接访问服务器的。但由于服务端拒绝对某个用户的访问,那么我们可以通过一个代理去访问这个服务端!!!
- 反向代理
反向代理就是: 客户端请求服务端会直接先经过代理,然后代理去选择走哪个服务器!!!!
2.常见服务器对比
(1).公司介绍
在介绍这一节内容之前,我们先来认识一家公司叫Netcraft。
Netcraft
公司于1994年底在英国成立,多年来一直致力于互联网市场以及在线安全方面的咨询服务,其中在国际上最具影响力的当属其针对网站服务器、SSL市场所做的客观严谨的分析研究,公司官网每月公布的调研数据(Web Server Survey)已成为当今人们了解全球网站数量以及服务器市场分额情况的主要参考依据,时常被诸如华尔街杂志,英国BBC,Slashdot等媒体报道或引用。
我们先来看一组数据,我们先打开Nginx的官方网站 http://nginx.org/,找到Netcraft公司公布的数据,对当前主流服务器产品进行介绍。
上面这张图展示了2019年全球主流Web服务器的市场情况,其中有Apache、Microsoft-IIS、google Servers、Nginx、Tomcat等,而我们在了解新事物的时候,往往习惯通过类比来帮助自己理解事物的概貌。
所以下面我们把几种常见的服务器来给大家简单介绍下:
(2).lls 服务器
全称(Internet Information Services)即互联网信息服务,是由微软公司提供的基于windows
系统的互联网基本服务。windows作为服务器在稳定性与其他一些性能上都不如类UNIX操作系统,因此在需要高性能Web服务器的场合下,IIS可能就会被"冷落".
(3).Tomcat 服务器
Tomcat是一个运行Servlet
和JSP
的Web应用软件,Tomcat技术先进、性能稳定而且开放源代码,因此深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。但是Tomcat天生是一个重量级的Web服务器,对静态文件和高并发的处理比较弱。最高并发量在 (200-300)。
(4).Apache 服务器
Apache的发展时期很长,同时也有过一段辉煌的业绩。从上图可以看出大概在2014年以前都是市场份额第一的服务器。Apache有很多优点,如稳定、开源、跨平台等。但是它出现的时间太久了,在它兴起的年代,互联网的产业规模远远不如今天,所以它被设计成一个重量级的、不支持高并发的Web服务器。在Apache服务器上,如果有数以万计的并发HTTP请求同时访问,就会导致服务器上消耗大量能存,操作系统内核对成百上千的Apache进程做进程间切换也会消耗大量的CUP资源,并导致HTTP请求的平均响应速度降低,这些都决定了Apache不可能成为高性能的Web服务器。这也促使了Lighttpd和Nginx的出现
。
(5).Lighttpd 服务器
Lighttpd是德国的一个开源的Web服务器软件,它和Nginx一样,都是轻量级、高性能的Web服务器,欧美的业界开发者比较钟爱Lighttpd,而国内的公司更多的青睐Nginx,同时网上Nginx的资源要更丰富些。
(6).其他的服务器
Google Servers
,Weblogic
, Webshpere(IBM)
…
经过各个服务器的对比,种种迹象都表明,Nginx将以性能为王。这也是我们为什么选择Nginx的理由。
3.Nginx的优点
(1).速度更快、并发更高
单次请求或者高并发请求的环境下,Nginx都会比其他Web服务器响应的速度更快。一方面在正常情况下,单次请求会得到更快的响应,另一方面,在高峰期(如有数以万计的并发请求),Nginx比其他Web服务器更快的响应请求。Nginx之所以有这么高的并发处理能力和这么好的性能原因在于Nginx采用了多进程和I/O多路复用(epoll)的底层实现。
(2).配置简单,扩展性强
Nginx的设计极具扩展性,它本身就是由很多模块组成,这些模块的使用可以通过配置文件的配置来添加。这些模块有官方提供的也有第三方提供的模块,如果需要完全可以开发服务自己业务特性的定制模块。
(3).高可靠性
Nginx采用的是多进程模式运行,其中有一个master主进程和N多个worker进程,worker进程的数量我们可以手动设置,每个worker进程之间都是相互独立提供服务,并且master主进程可以在某一个worker进程出错时,快速去"拉起"新的worker进程提供服务。
(4).热部署
现在互联网项目都要求以7*24小时进行服务的提供,针对于这一要求,Nginx也提供了热部署功能,即可以在Nginx不停止的情况下,对Nginx进行文件升级、更新配置和更换日志文件等功能。
(5).成本低、BSD许可证
BSD是一个开源的许可证,世界上的开源许可证有很多,现在比较流行的有六种分别是GPL、BSD、MIT、Mozilla、Apache、LGPL。这六种的区别是什么,我们可以通过下面一张图来解释下:
Nginx本身是开源的,我们不仅可以免费的将Nginx应用在商业领域,而且还可以在项目中直接修改Nginx的源码来定制自己的特殊要求。这些点也都是Nginx为什么能吸引无数开发者继续为Nginx来贡献自己的智慧和青春。OpenRestry [Nginx+Lua] Tengine[淘宝]。
4.Nginx的功能特性及常用功能
Nginx提供的基本功能服务从大体上归纳为"基本HTTP服务"、“高级HTTP服务”和"邮件服务"等三大类。
(1).基本HTTP服务
Nginx可以提供基本HTTP服务,可以作为HTTP代理服务器和反向代理服务器,支持通过缓存加速访问,可以完成简单的负载均衡和容错,支持包过滤功能,支持SSL等。
- 处理静态文件、处理索引文件以及支持自动索引;
- 提供反向代理服务器,并可以使用缓存加上反向代理,同时完成负载均衡和容错;
- 提供对FastCGI、memcached等服务的缓存机制,,同时完成负载均衡和容错;
- 使用Nginx的模块化特性提供过滤器功能。Nginx基本过滤器包括gzip压缩、ranges支持、chunked响应、XSLT、SSI以及图像缩放等。其中针对包含多个SSI的页面,经由FastCGI或反向代理,SSI过滤器可以并行处理。
- 支持HTTP下的安全套接层安全协议SSL.
- 支持基于加权和依赖的优先权的HTTP/2
(2).高级HTTP服务
- 支持基于名字和IP的虚拟主机设置
- 支持HTTP/1.0中的KEEP-Alive模式和管线(PipeLined)模型连接
- 自定义访问日志格式、带缓存的日志写操作以及快速日志轮转。
- 提供3xx~5xx错误代码重定向功能
- 支持重写(Rewrite)模块扩展
- 支持重新加载配置以及在线升级时无需中断正在处理的请求
- 支持网络监控
- 支持FLV和MP4流媒体传输
(3).邮件服务
Nginx提供邮件代理服务也是其基本开发需求之一,主要包含以下特
性:
- 支持IMPA/POP3代理服务功能
- 支持内部SMTP代理服务功能
(4).Nginx常用的功能模块
静态资源部署
Rewrite地址重写
正则表达式
反向代理
负载均衡
轮询、加权轮询、ip_hash、url_hash、fair
Web缓存
环境部署
高可用的环境
用户认证模块...
Nginx的核心组成
nginx 二进制可执行文件
nginx.conf 配置文件
error.log 错误的日志记录
access.log 访问日志记录
(二)、Nginx 环境准备
1.Nginx版本介绍
Nginx的官方网站为: http://nginx.org
打开源码可以看到如下的页面内容
Nginx的官方下载网站为http://nginx.org/en/download.html,当然你也可以之间在首页选中右边的download进入版本下载网页。在下载页面我们会看到如下内容:
2.准备服务器系统
(1).环境准备
- 确认centos的内核
准备一个内核为2.6及以上版本的操作系统,因为linux2.6及以上内核才支持epoll,而Nginx需要解决高并发压力问题是需要用到epoll,所以我们需要有这样的版本要求。
我们可以使用uname -a
命令来查询linux的内核版本。
- 确认centos能够连接网络
ping www.baidu.com
- 确认关闭防火墙
这一项的要求仅针对于那些对linux系统的防火墙设置规则不太清楚的,建议大家把防火墙都关闭掉,因为我们此次课程主要的内容是对Nginx的学习,把防火墙关闭掉,可以省掉后续Nginx学习过程中遇到的诸多问题。
关闭的方式有如下两种:
// 关闭运行的防火墙,系统重新启动后,防火墙将重新打开
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
查看状态
如果查看不是disabled状态,我们可以通过修改配置文件来进行设置,修改SELINUX=disabled
,然后重启下系统即可生效。
vim /etc/selinux/config
3.Nginx安装方式介绍
Nginx的安装方式有两种分别是:
通过Nginx源码
通过Nginx源码简单安装 (1)
通过Nginx源码复杂安装 (3)
通过yum安装 (2)
(1).通过Nginx源码安装
第一步: 安装gcc编译器
Nginx是使用C语言编写的程序,因此想要运行Nginx就需要安装一个编译工具。GCC就是一个开源的编译器集合,用于处理各种各样的语言,其中就包含了C语言。
使用命令 yum install -y gcc
来安装
安装成功后,可以通过gcc --version
来查看gcc是否安装成功
第二步: 安装PRCE
Nginx在编译过程中需要使用到PCRE库(perl Compatible RegularExpressoin 兼容正则表达式库),因为在Nginx的Rewrite模块和http核心模块都会使用到PCRE正则表达式语法。
可以使用命令 yum install -y pcre pcre-devel
来进行安装
安装成功后,可以通过rpm -qa pcre pcre-devel
来查看是否安装成功
第三步: zlib
zlib库提供了开发人员的压缩算法,在Nginx的各个模块中需要使用gzip压缩,所以我们也需要提前安装其库及源代码zlib和zlib-devel
可以使用命令 yum install -y zlib zlib-devel
来进行安装
安装成功后,可以通过rpm -qa zlib zlib-devel
来查看是否安装成功
第四步: OpenSSL
OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包进行安全通信,并且避免被窃听。
SSL:Secure Sockets Layer安全套接协议的缩写,可以在Internet上提供秘密性传输,其目标是保证两个应用间通信的保密性和可靠性。在Nginx中,如果服务器需要提供安全网页时就需要用到OpenSSL
库,所以我们需要对OpenSSL
的库文件及它的开发安装包进行一个安装。
可以使用命令yum install -y openssl openssl-devel
来进行安装
安装成功后,可以通过rpm -qa openssl openssl-devel
来查看是否安装成功
第五步: 汇总上面四步
上述命令,一个个来的话比较麻烦,我们也可以通过一条命令来进行安装yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
进行全部安装。
(2).Nginx的源码简单安装 (第一种)
- 进入官网查找需要下载版本的链接地址,然后使用wget命令进行下载
wget http://nginx.org/download/nginx-1.16.1.tar.gz
- 建议大家将下载的资源进行包管理
mkdir -p nginx/core
mv nginx-1.16.1.tar.gz nginx/core
- 解压缩
cd /root/nginx/core
tar -xzf nginx-1.16.1.tar.gz
- 进入资源文件中,发现configure
./configure 我们没有指定安装位置默认安装在 /usr/local/nginx
cd /root/nginx/core/nginx-1.16.1
./configure
- 安装
cd /root/nginx/core/nginx-1.16.1
make install
- 查看安装的位置
where
- 启动我们的nginx
cd /usr/local/nginx/sbin
./nginx
点击访问我们的首页: http://8.130.48.9/ 发现启动成功
- 假如错误的话,我们一定要进行80端口的关闭处理操作。
- 假如说在访问网址的时候一直转圈圈请查看是否关闭防火墙。
(3).Nginx的yum安装 (第二种)
http://nginx.org/en/linux_packages.html#RHEL
使用源码进行简单安装,我们会发现安装的过程比较繁琐,需要提前准备GCC编译器、PCRE兼容正则表达式库、zlib压缩库、OpenSSL安全通信的软件库包,然后才能进行Nginx的安装。
- 安装yum-utils
sudo yum install -y yum-utils
- 添加yum源文件
vim /etc/yum.repos.d/nginx.repo
配置如下的内容
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
- 查看是否安装成功
yum list | grep nginx
- 使用yum进行安装
yun install -y nginx
- 查看nginx的安装位置
whereis nginx
- 启动测试
(4).源码简单安装和yum安装的差异:
这里先介绍一个命令: ./nginx -V
,通过该命令可以查看到所安装Nginx的版本及相关配置信息。
- 简单安装
2. yum安装
(5).查看nginx的目录
cd /root/nginx/core/nginx-1.16.1
内容解释:
auto
: 存放的是编译相关的脚本CHANGES
: 版本变更记录CHANGES.ru
: 俄罗斯文的版本变更记录conf
: nginx默认的配置文件configure
: nginx软件的自动脚本程序,是一个比较重要的文件,作用如下:- 检测环境及根据环境检测结果生成C代码
- 生成编译代码需要的 Makefile文件
contrib
: 存放的是几个特殊的脚本文件,其中README中对脚本有着详细的说明html
: 存放的是Nginx自带的两个html页面,访问Nginx的首页和错误页面LICENSE
: 许可证的相关描述文件man
: nginx的man手册README
: Nginx的阅读指南src
: Nginx的源代码
(6).Nginx的源码复杂安装 (第三种)
这种方式和简单的安装配置不同的地方在第一步,通过./configure
来对编译参数进行设置,需要我们手动来指定。那么都有哪些参数可以进行设置,接下来我们进行一个详细的说明。
- PATH: 是和路径相关的配置信息
- with: 是启动模块,默认是关闭的
- without: 是关闭模块,默认是开启的
我们先来认识一些简单的路径配置已经通过这些配置来完成一个简单的编译:
–prefix=PATH (安装路径)
指向Nginx的安装目录,默认值为/usr/local/nginx
–sbin-path=PATH (可执行的nginx文件)
指向(执行)程序文件(nginx)的路径,默认值为<prefix>/sbin/nginx
–modules-path=PATH (安装目录)
指向Nginx动态模块安装目录,默认值为<prefix>/modules
–conf-path=PATH (配置文件)
指向配置文件(nginx.conf)的路径,默认值为
<prefix>/conf/nginx.conf
–error-log-path=PATH (错误日志文件)
指向错误日志文件的路径,默认值为<prefix>/logs/error.log
–http-log-path=PATH (日志文件路径)
指向访问日志文件的路径,默认值为<prefix>/logs/access.log
–pid-path=PATH (文件路径)
指向Nginx启动后进行ID的文件路径,默认值为
<prefix>/logs/nginx.pid
–lock-path=PATH (nginx锁的路径)
指向Nginx锁文件的存放路径,默认值为<prefix>/logs/nginx.lock
第一步: 将以前的Nginx进行删除的操作
第二步: 进行编译的操作
cd /root/nginx/core/nginx-1.16.1
在上面的那个路径进行编译
./configure --prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--modules-path=/usr/local/nginx/modules \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--lock-path=/usr/local/nginx/logs/nginx.lock
编译成功!!
第三步: 安装操作
make install
安装成功
第四步: 进行开启并测试
// 进入我们nginx的安装目录
cd /usr/local/nginx/sbin
// 启动
./nginx
测试成功!!!!
(7).Nginx删除的三步走
步骤一: 需要将nginx的进程关闭
// 既然怒我们的sbin可执行程序位置
cd /usr/local/nginx/sbin
./nginx -s stop
步骤二:将安装的nginx进行删除
rm -rf /usr/local/nginx
步骤三: 将安装包之前编译的环境清除掉
// 进入我们的安装包
cd /root/nginx/core/nginx-1.16.1
// 清除操作
make clean
4. Nginx目录结构分析
(1).安装我们的tree工具
在使用 Nginx 之前,我们先对安装好的 Nginx 目录文件进行一个分析,在这块给大家介绍一个工具 tree,通过tree我们可以很方面的去查看centos系统上的文件目录结构,当然,如果想使用tree工具,就得先通过 yum install -y tree
来进行安装,安装成功后,可以通过执行 tree /usr/local/nginx
(tree后面跟的是Nginx的安装目录),获取的结果如下:
(2).Nginx的目录结构
tree /usr/local/nginx
- conf: nginx所有配置文件目录
- CGI(Common Gateway Interface)通用网关【接口】,主要解决的问题是从客户端发送一个请求和数据,服务端获取到请求和数据后可以调用调用CGI【程序】处理及相应结果给客户端的一种标准规范。
- fastcgi.conf: fastcgi相关配置文件
- fastcgi.conf.default: fastcgi.conf的备份文件
- fastcgi_params: fastcgi的参数文件
- fastcgi_params.default: fastcgi的参数备份文件
- scgi_params: scgi的参数文件
- scgi_params.default:scgi的参数备份文件
- uwsgi_params: uwsgi的参数文件
- uwsgi_params.default: uwsgi的参数备份文件
- mime.types: 记录的是HTTP协议中的Content-Type的值和文件后缀名的对应关系
- mime.types.default: mime.types的备份文件
- nginx.conf: 这个是Nginx的核心配置文件,这个文件非常重要,也是我们即将要学习的重点
- nginx.conf.default: nginx.conf的备份文件
koi-utf、koi-win、win-utf这三个文件都是与编码转换映射相关的配置文件,用来将一种编码转换成另一种编码
- html:存放nginx自带的两个静态的html页面
- 50x.html: 访问失败后的失败页面
- index.html: 成功访问的默认首页
- logs:记录入门的文件,当nginx服务器启动后,这里面会有 access.log (访问日志)、error.log(错误日志) 和nginx.pid(当前Nginx运行的进程PID号) 三个文件出现。
- sbin: 是存放执行程序文件nginx
- nginx是用来控制Nginx的启动和停止等相关的命令。
5. Nginx服务器的启停命令
Nginx安装完成后,接下来我们要学习的是如何启动、重启和停止Nginx的服务。
对于Nginx的启停在linux系统中也有很多种方式,我们本次课程介绍两种方式:
- Nginx服务的信号控制
- Nginx的命令行控制
(1).方式一:Nginx服务的信号控制
Nginx中的master和worker进程?
Nginx的工作方式?
如何获取进程的PID?
信号有哪些?
如何通过信号控制Nginx的启停等相关操作?
前面在提到Nginx的高性能,其实也和它的架构模式有关。Nginx默认采用的是多进程的方式来工作的,当将Nginx启动后,我们通过ps -ef |grep nginx
命令可以查看到如下内容:
从上图中可以看到,Nginx后台进程中包含一个master进程和多个worker进程,master进程主要用来管理worker进程,包含接收外界的信息,并将接收到的信号发送给各个worker进程,监控worker进程的状态,当worker进程出现异常退出后,会自动重新启动新的worker进程。而worker进程则是专门用来处理用户请求的,各个worker进程之间是平等的并且相互独立,处理请求的机会也是一样的。nginx的进程模型,我们可以通过下图来说明下
我们现在作为管理员,只需要通过给master进程发送信号就可以来控制Nginx,这个时候我们需要有两个前提条件,一个是要操作的master进程,一个是信号。
-
要想操作Nginx的master进程,就需要获取到master进程的进程号ID。获取方式简单介绍两个,
- 方式一:通过
ps -ef | grep nginx
; - 方式二:在讲解nginx的
./configure
的配置参数的时候,有一个参数是--pid-path=PATH
默认是/usr/local/nginx/logs/nginx.pid
,所以可以通过查看该文件来获取nginx的master进程ID.
- 方式一:通过
- 信号
调用命令为 kill -signal PID
signal: 即为信号;PID即为获取到的master线程ID
more /usr/local/nginx/logs/nginx.pid
: 相当于获得nginx的pid的值做为返回值!!!
// 利用飘号我们可以获取指定文件的值
` more /usr/local/nginx/logs/nginx.pid`
- 发送TERM/INT信号给master进程,会将Nginx服务
立即关闭
。
// 强制关闭master进程
kill -TERM PID
kill -TERM `more /usr/local/nginx/logs/nginx.pid`
// 强制关闭master进程
kill -INT PID
kill -INT `more /usr/local/nginx/logs/nginx.pid`
- 发送QUIT信号给master进程,master进程会控制所有的work进程不再接收新的请求,等所有请求处理完后,在把进程都关闭掉。
// 优雅的关闭worker进程
kill -QUIT PID
kill -QUIT `more /usr/local/nginx/logs/nginx.pid`
- 发送HUP信号给master进程,master进程会把
控制旧的work进程不再接收新的请求
,等处理完请求后将旧的work进程关闭掉,然后根据nginx的配置文件重新启动新的work进程
。
// 关闭旧的worker进程,开启新的worker进程
kill -HUP PID
kill -HUP PID `more /usr/local/nginx/logs/nginx.pid`
- 发送USR1信号给master进程,告诉
Nginx重新开启日志文件
// 重新开启我们的日志文件
kill -USR1 PID
kill -USR1 `more /usr/local/nginx/logs/nginx.pid`
- 发送USR2信号给master进程,告诉master进程要
平滑升级
,这个时候,会重新开启对应的master进程和work进程,整个系统中将会有两个master进程,并且新的master进程的PID会被记录在/usr/local/nginx/logs/nginx.pid
而之前的旧的master进程PID会被记录在/usr/local/nginx/logs/nginx.pid.oldbin
文件中,接着再次发送QUIT信号给旧的master进程,让其处理完请求后再进行关闭
// 第一步进行平滑升级
kill -USR2 PID
kill -USR2 `more /usr/local/nginx/logs/nginx.pid`
// 第二步: 优雅的删除旧的值
kill -QUIT PID
kill -QUIT `/usr/local/nginx/logs/nginx.pid.oldbin`
6. 发送WINCH信号给master进程,让master进程控制不让所有的work进程在接收新的请求了,请求处理完后关闭work进程。注意master进程不会被关闭掉
// 不再接受新的请求了,处理完毕后只会关闭worker不会master
kill -WINCH PID
kill -WINCH `/usr/local/nginx/logs/nginx.pid`
(2).方式2: Nginx的命令行控制
此方式是通过Nginx
安装目录下的sbin
下的可执行文件nginx
来进行Nginx状态的控制,我们可以通过nginx -h
来查看都有哪些参数可以用:
-?
和-h
:显示帮助信息-v
:打印版本号信息并退出-V
:打印版本号信息和配置信息并退出-t
:检查nginx的配置文件语法nginx.conf是否正确并退出-T
:测试nginx的配置文件语法是否正确并列出用到的配置文件信息然后退出-q
:在配置测试期间禁止显示非错误消息 (也就是只显示错误信息)-s
: signal信号,后面可以跟 :列如语法:./nginx -s stop- stop[快速关闭,类似于TERM/INT信号的作用]
- quit[优雅的关闭,类似于QUIT信号的作用]
- reopen[重新打开日志文件类似于USR1信号的作用]
- reload[类似于HUP信号的作用] (重新加载配置文件)
-p
:prefix,指定Nginx的prefix路径,(默认为: /usr/local/nginx/)-c
:filename,指定Nginx的配置文件路径,(默认为: conf/nginx.conf)-g
:用来补充Nginx配置文件,向Nginx服务指定启动时应用全局的配置
6.Nginx服务器版本升级和新增模块
(1).需求提出
如果想对Nginx的版本进行更新,或者要应用一些新的模块,最简单的做法就是停止当前的Nginx服务,然后开启新的Nginx服务。但是这样会导致在一段时间内,用户是无法访问服务器。为了解决这个问题,我们就需要用到Nginx服务器提供的平滑升级功能。这个也是Nginx的一大特点,使用这种方式,就可以使Nginx在7*24小时不间断的提供服务了。接下来我们分析下需求:
需求:Nginx的版本最开始使用的是Nginx-1.14.2,由于服务升级,需
要将Nginx的版本升级到Nginx-1.16.1,要求Nginx不能中断提供服务。
为了应对上述的需求,这里我们给大家提供两种解决方案:
- 方案一:使用Nginx服务信号完成Nginx的升级
- 方案二:使用Nginx安装目录的make命令完成升级
(2).环境准备
-
先准备两个版本的Nginx分别是
1.14.2
和1.16.1
-
使用Nginx源码安装的方式将
1.14.2
版本安装成功并正确访问
进入安装目录
./configure
make && make install
- 将Nginx1.16.1进行参数配置和编译,不需要进行安装。
进入安装目录
./configure
make
(3).使用Nginx服务信号进行升级 (方案一)
第一步: 将1.14.2版本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold
第二步:将
Nginx1.16.1
安装目录编译后的objs目录下的nginx文件,拷贝到原来/usr/local/nginx/sbin
目录下
cd ~/nginx/core/nginx-1.16.1/objs
cp nginx /usr/local/nginx/sbin
第三步:发送信号
USR2
给Nginx的1.14.2版本对应的master进程
第四步:发送信号
QUIT
给Nginx的1.14.2版本对应的master进程
kill -QUIT `more /usr/local/logs/nginx.pid.oldbin`
(4).使用Nginx安装目录的make命令完成升级 (方案二)
第一步: 将
1.14.2
版本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold
第二步: 将Nginx1.16.1安装目录编译后的objs目录下的nginx文件,拷贝到原来
/usr/local/nginx/sbin
目录下
cd ~/nginx/core/nginx-1.16.1/objs
cp nginx /usr/local/nginx/sbin
第三步: 进入到新版本安装目录
/root/nginx/core/nginx-1.16.1
,执行make upgrade
第四步: 查看是否更新成功
./nginx -v
在整个过程中,其实Nginx是一直对外提供服务的。并且当Nginx的服务器启动成功后,我们是可以通过浏览器进行直接访问的,同时我们可以通过更改html目录下的页面来修改我们在页面上所看到的内容,那么问题来了,为什么我们要修改html目录下的文件,能不能多添加一些页面是Nginx的功能更加丰富,还有前面聊到Nginx的前端功能又是如何来实现的,这就需要我们对Nginx的核心配置文件进行一个详细的学习。
(三)、Nginx核心配置文件结构
简化版Nginx核心配置文件
从前面的内容学习中,我们知道Nginx的核心配置文件默认是放在 /usr/local/nginx/conf/nginx.conf
,这一节,我们就来学习下nginx.conf
的内容和基本配置方法。
读取Nginx自带的Nginx配置文件,我们将其中的注释部分【学习一个技术点就是在Nginx的配置文件中可以使用#来注释】删除掉后,就剩下下面内容:
worker_processes 1; #全局块: 指令名->指令值
events { #用来配置Nginx与用户网络相关的内容
worker_connections 1024;
}
http { # Nginx最重要的部分
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server { #一个http块里面可以配置多个server块
# 会监听 localhost:80这个端口
listen 80; # 被监听的端口
server_name localhost; # 被监听的IP
location / { # 当访问 / 的时候跳转到哪里?
root html; #在/usr/local/nginx/html目录下的
index index.html index.htm; #首页跳转的位置 (欢迎页)
}
error_page 500 502 503 504 /50x.html; # 服务端出现下面的状态码的时候,跳转到哪里?
location = /50x.html {
root html; #在/usr/local/nginx/html目录下的
}
}
}
#全局块,主要设置Nginx服务器整体运行的配置指令
指令名 指令值;
#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对Nginx服务器的性能影响较大
events{
指令名 指令值;
}
#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、第三方模块配置...
http{
server{ #server块,是Nginx配置和虚拟主机相关的内容指令名 指令值;
location/{
#location块,基于Nginx服务器接收请求字符串与location后面的值进行匹配,对特定请求进行处理指令名 指令值;
}
}
...
}
简单小结下:
nginx.conf配置文件中默认有三大块:全局块、events块、http块。http块中可以配置多个server块,每个server块又可以配置多个location块。
1.全局块
(1).user指令
- user:用于配置运行Nginx服务器的worker进程的用户和用户组。
该属性也可以在编译的时候指定,语法如下 ./configure --user=user --group=group ,如果两个地方都进行了设置,最终生效的是配置文件中的配置。
该指令的使用步骤:
(1).在配置文件(nginx.conf)中设置一个用户信息"www"
user www;
(2).在 /usr/local/nginx/sbin
进行检测我们的配置文件
./nginx -t
(3).因为我们报错,提示找不到 "www"这个用户那么我们就创建
cd /usr/local/nginx/sbin
useradd www
(4).当我们添加用户之后并重新加载我们的文件,检查我们的nginx之后发现我们的worker发生了改变。ps -ef|grep nginx
(5).将默认的index.html更改成我们自定义的index.html
cd /root
mkdir html
cd html
vim index.html
在index.html中编辑如下信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
}
body {
height: 100%;
}
.container {
height: 100%;
background-image: linear-gradient(to right, #999999, #330867);
}
.login-wrapper {
background-color: bisque;
width: 358px;
height: 588px;
border-radius: 15px;
padding: 0 50px;
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
.header {
font-size: 38px;
font-weight: bold;
text-align: center;
line-height: 200px;
}
.input-item {
display: block;
width: 100%;
margin-bottom: 20px;
border: 0;
padding: 10px;
border-bottom: 1px solid rgb(128,125,125);
font-size: 15px;
outline: none;
}
.input-item::placeholder {
text-transform: uppercase;
}
.btn {
text-align: center;
padding: 10px;
width: 100%;
margin-top: 40px;
background-image: linear-gradient(to right,#a6c1ee, #fbc2eb);
color: #fff;
}
.msg {
text-align: center;
line-height: 88px;
}
a {
text-decoration-line: none;
color: #abc1ee;
}
</style>
</head>
<body>
<div class="container">
<div class="login-wrapper">
<div class="header">Login</div>
<div class="form-wrapper">
<input type="text" name="username" placeholder="username" class="input-item">
<input type="password" name="password" placeholder="password" class="input-item">
<div class="btn">Login</div>
</div>
<div class="msg">
Don't have account?
<a href="#">Sign up</a>
</div>
</div>
</div>
</body>
</html>
(6).去更改我们nginx.conf
将首页指定为我们自定义的
cd /usr/local/nginx/conf
vim nginx.conf
location / {
root /root/html; // ⭐⭐修改
index index.html index.htm;
}
(7).进行重新加载我们的配置文件
# 进入我们的sbin目录
cd /usr/local/nginx/sbin
# 重新加载我们的配置文件
./nginx -s reload
# 检查我们的配置文件
./nginx -t
http://8.130.48.9/ 我们发现报403权限不足的错误
(8).将我们的 /root/html
复制到我们的新建的用户目录下,当我们创建一个用户的时候 /home
就会创建一个同名的文件夹 将这个位置修改之后我们发现运行成功!!!
# 进入我们新创建的html文件夹中
cd /home/www
# 将我们的 /root/html 复制到当前目录下 -r连同html文件夹
cp -r /root/html/ ./
# 修改我们的配置文件
vim /usr/local/nginx/conf/nginx.conf
location / {
root /home/www/html; //⭐⭐
index index.html index.htm;
}
# 进入我们的sbin
cd /usr/local/nginx/sbin
# 进行重新加载
./nginx -s reload
# 进行检查配置文件
./nginx -t
再次访问我们发现不会报403错误了。
(9).为什么 /root/html
的不能访问到,然而 /home/www/html
能够访问到?
/home/www/html: 能访问是因为Nginx的worker线程也是www
cd /home
ll
/root/html: 不能被访问是因为权限不够Nginx的用户名是www,但是在/root/html要求的是root,所以权限不足!!!
cd /
ll
(2).work process指令
master_process: 用来指定是否开启工作进程(worker)。
worker_processes: 用于配置Nginx生成工作进程
的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process
的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。
如果将worker_processes设置成2,则会看到如下内容:
./nginx -s reload
./nginx -t
(3).其他指令
- daemon:设定Nginx是否以守护进程的方式启动。
守护式进程是linux后台执行的一种服务进程,特点是独立于控制终端,不会随着终端关闭而停止
。
什么是控制台终端?
- pid: 用来配置Nginx当前master进程的进程号ID存储的文件路径。
该属性可以通过 ./configure --pid-path=PATH
来指定
error_log
: 用来配置Nginx的错误日志存放路径
该属性可以通过 ./configure --error-log-path=PATH
来指定
其中日志级别的值有:
debug|info|notice|warn|error|crit|alert|emerg
,翻译过来为试|信
息|通知|警告|错误|临界|警报|紧急,这块建议大家设置的时候不要设置成info以下的等级,因为会带来大量的磁盘I/O消耗,影响Nginx的性能。
include: 用来引入其他配置文件,使Nginx的配置更加灵活
2.events块
accept_mutex
:用来设置Nginx网络连接序列化
这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒
,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢。
multi_accept
: 用来设置是否允许同时接收多个网络连接
如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接。 建议打开,设置多个!!!
worker_connections
:用来配置单个worker进程最大的连接数
这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量。
use
: 用来设置Nginx服务器选择哪种事件驱动来处理网络消息。
注意:此处所选择事件处理模型是Nginx优化部分的一个重要内容,method的可选值有 select/poll/epoll/kqueue
等,之前在准备centos环境的时候,我们强调过要使用linux内核在2.6以上,就是为了能使用epoll函数来优化Nginx。 建议设置成 use epoll !!!
另外这些值的选择,我们也可以在编译的时候使用--with-select_module
、--without-select_module
、--with-poll_module
、--without-poll_module
来设置是否需要将对应的事件驱动模块编译到Nginx的内核。
(1).events指令配置实列
打开Nginx的配置文件 nginx.conf
,添加如下配置
vim /usr/local/nginx/conf/nginx.conf
events {
accept_mutex on;
multi_accept on;
worker_connections 1024;
use epoll;
}
启动测试:
cd /usr/local/nginx/sbin
./nginx -t
./nginx -s reload
3.http块
(1).定义MIME-Type
我们都知道浏览器中可以显示的内容有HTML、XML、GI
F等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIMEType。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型。
在Nginx的配置文件中,默认有两行配置
include mime.types;
default_type application/octet-stream;
default_type
:用来配置Nginx响应前端请求默认的MIME类型。
在default_type之前还有一句include mime.types ,include之前我们已经介绍过,相当于把mime.types文件中MIMT类型与相关类型文件的文件后缀名的对应关系加入到当前的配置文件
中。
举例来说明:
有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响应性能非常快。
如何实现:
location /get_text {
return 200 "<h1>This is Nginx's Text</h1>";
}
测试: http://8.130.48.9/get_text 我们发现以下载的方式响应我们,原因是默认的是 application/octet-stream
二进制流响应
为了让结果得到的是是json文本文档,我们需要修改 default_type
;
仅在 /get_text 这个路径下设置这个类型!!!!
location /get_text {
default_type text/plain; // plain不会解析文本;text/html 会解析我们的文本(也就是说会解析html特殊语法)
return 200 "<h1>This is Nginx's Text</h1>";
}
对Nginx进行我们的重新测试操作!!!
测试: http://8.130.48.9/get_text 我们发现这个是展示文本并没有解析,因为我们设置的是 : text/plain
(不解析特殊语法)
假如访问的是 /get_json 那么我们将会返回json
location /get_json{
default_type application/json; //这里返回的是的json字符串数据
return 200 '{"name":"TOM","age":18}';
}
(2).自定义服务日志
Nginx中日志的类型分 access.log
、error.log
。
access.log
: 用来记录用户所有的访问请求。
// 动态监视我们的access.log日志
tail -f /usr/local/nginx/logs/access.log
当我们进行一次访问我们的nginx的时候,我们会发现监视日志的窗口会立刻生成一个。
error.log
: 记录nginx本身运行时的错误信息,不会记录用户的访问请求。
Nginx服务器支持对服务日志的格式、大小、输出
等进行设置,需要使用到两个指令,分别是access_log和log_format指令。
- access_log:用来设置用户访问日志的相关属性。
我们可以自定义我们的acess_log的路径:
- log_format:用来指定日志的输出格式。
我们可以自定义我们的这个日志格式
(3).其他配置指令
- sendfile: 用来设置Nginx服务器是否使用sendfile()传输文件,
该属性可以大大提高Nginx处理静态资源的性能
- keepalive_timeout:用来设置长连接的超时时间。
为什么要使用keepalive
?
我们都知道HTTP是一种无状态协议
,客户端向服务端发送一个TCP请求,服务端响应完毕后断开连接。
因为我们的TCP连接使用的是 三次握手四次挥手。所以每次连接的时候都要重新连接一下 !
如何客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive
模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率。但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。
- keepalive_requests:用来设置一个keep-alive连接使用的次数。
当次数达到100次之后,自动断开
4.server块和location块
server块
和location块
都是我们要重点讲解和学习的内容,因为我们后面会对Nginx的功能进行详细讲解,所以这块内容就放到静态资源部署的地方给大家详细说明。
本节我们主要来认识下Nginx默认给的nginx.conf中的相关内容,以及server块与location块在使用的时候需要注意的一些内容。
server { #一个http块里面可以配置多个server块
# 会监听 localhost:80这个端口
listen 80; # 被监听的端口
server_name localhost; # 被监听的IP
location / { # 当访问 / 的时候跳转到哪里?
root html; #在/usr/local/nginx/html目录下的
index index.html index.htm; #首页跳转的位置 (欢迎页)
}
error_page 500 502 503 504 /50x.html; # 服务端出现下面的状态码的时候,跳转到哪里?
location = /50x.html {2
root html; #在/usr/local/nginx/html目录下的
}
}
(四)、Nginx进阶篇
1.Nginx服务器基础配置
前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述。通过这些指令的合理配置,我们就可以让一台Nginx服务器正常工作,并且提供基本的web服务器功能。
接下来我们将通过一个比较完整和最简单的基础配置实例,来巩固下前面所学习的指令及其配置。
(1).需求提出
(1)有如下访问:
http://8.130.48.9:8081/server1/location1
访问的是:index_sr1_location1.html
http://8.130.48.9:8081/server1/location2
访问的是:index_sr1_location2.html
http://8.130.48.9:8082/server2/location1
访问的是:index_sr2_location1.html
http://8.130.48.9:8082/server2/location2
访问的是:index_sr2_location2.html
(2)如果访问的资源不存在:
返回自定义的404页面
(3)将/server1和/server2的配置使用不同的配置文件分割:
将文件放到/home/www/conf.d目录下,然后使用include进行合并
(4)为/server1和/server2各自创建一个访问日志文件
(2).环境搭建
- 创建静态资源
具体的日志文件我们不能手动创建,Nginx会自动帮助我们创建,假如我们自己创建了,那么日志信息不会输出。
- 新建一个我们的nginx.conf,旧的先进行备份处理
cd /usr/local/nginx/conf
mv nginx.conf nginx1.conf
vim 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;
}
}
}
在初始化的基础上再进行如下配置:
##全局块 begin##
#配置允许运行Nginx工作进程的用户和用户组
user www;
#配置运行Nginx进程生成的worker进程数
worker_processes 2;
#配置Nginx服务器运行对错误日志存放的路径
error_log logs/error.log;
#配置Nginx服务器允许时记录Nginx的master进程的PID文件路径和名称
pid logs/nginx.pid;
#配置Nginx服务是否以守护进程方法启动
#daemon on;
##全局块 end##
##events块 begin##
events{
#设置Nginx网络连接序列化
accept_mutex on;
#设置Nginx的worker进程是否可以同时接收多个请求
multi_accept on;
#设置Nginx的worker进程最大的连接数
worker_connections 1024;
#设置Nginx使用的事件驱动模型
use epoll;
}
##events块 end##
##http块 start##
http{
#定义MIME-Type
include mime.types;
default_type application/octet-stream;
#配置允许使用sendfile方式运输
sendfile on;
#配置连接超时时间
keepalive_timeout 65;
#配置请求处理日志格式
log_format server1 '===>server1 access log';
log_format server2 '===>server2 access log';
##server块 开始##
include /home/www/conf.d/*.conf;
##server块 结束##
}
- 配置完成后如下:
user www; # 使用这个用户信息
worker_processes 1;
error_log logs/error.log; # 错误日志
pid logs/nginx.pid; #master的pid
daemon on; #守护线程
events {
accept_mutex on; # 允许接受多个网络连接
multi_accept on;
use epoll; # 使用epoll驱动
worker_connections 1024; # 最大连接数为1024
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 设置我们的格式
log_format server1 '=====>server1 access log format';
log_format server2 '=====>server2 access log format';
# 在home目录下的www/conf.d文件夹下的所有 .conf都会进行引入进来
include /home/www/conf.d/*.conf;
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;
}
}
- 配置我们 /home/www/con.f/ 下面的内容
vim /home/www/conf.d/server1.conf
配置我们server1的配置文件 server1.conf
server {
listen 8081;
server_name localhost;
access_log /home/www/myweb/server1/logs/access.log server1;
location /server1/location1{
root /home/www/myweb;
index index_strl_location1.html;
}
location /server1/location2{
root /home/www/myweb;
index index_strl_location2.html;
}
error_page 404 /404.html;
location = 404.html {
root /home/www/myweb;
index 404.html;
}
}
配置我们的server2的配置文件 servre2.conf
vim /home/www/conf.d/server2.conf
server {
listen 8082;
server_name localhost;
access_log /home/www/myweb/server2/logs/access.log server2;
location /server2/location1{
root /home/www/myweb;
index index_str2_location1.html;
}
location /server2/location2{
root /home/www/myweb;
index index_str2_location2.html;
}
error_page 404 /404.html;
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
(3).测试需求
测试: http://8.130.48.9:8081/server1/location1/
http://8.130.48.9:8081/server1/location2/
http://8.130.48.9:8082/server2/location2/
http://8.130.48.9:8082/server2/location1/
访问不存在的路径: http://8.130.48.9:8082/server2/location5/
实时监控我们的日志信息,我们会发现我们的日志发生了变化。
2.Nginx服务操作的问题
经过前面的操作,我们会发现,如果想要启动、关闭或重新加载nginx配置文件
,都需要先进入到nginx的安装目录的sbin目录,然后使用nginx的二级制可执行文件来操作,相对来说操作比较繁琐,这块该如何优化?另外如果我们想把Nginx设置成随着服务器启动就自动完成启动操作,又该如何来实现?这就需要用到接下来我们要讲解的两个知识点:
Nginx配置成系统服务
Nginx命令配置到系统环境
(1). Nginx配置成系统服务
把Nginx应用服务设置成为系统服务,方便对Nginx服务的启动和停止等相关操作,具体实现步骤:
- 在
/usr/lib/systemd/system
目录下添加nginx.service
,内容如下:
vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.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
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=default.target
- 添加完成后如果权限有问题需要进行权限设置
chmod 755 /usr/lib/systemd/system/nginx.service
- 重新加载一下我们的整个系统
systemctl daemon-reload
- 使用系统命令来操作Nginx服务
启动: systemctl start nginx
停止: systemctl stop nginx
重启: systemctl restart nginx
重新加载配置文件: systemctl reload nginx
查看nginx状态: systemctl status nginx
开机启动: systemctl enable nginx
(2).Nginx命令配置到系统环境
前面我们介绍过Nginx安装目录下的二级制可执行文件nginx的很多命令,要想使用这些命令前提是需要进入sbin目录下才能使用,很不方便,如何去优化,我们可以将该二进制可执行文件加入到系统的环境变量,这样的话在任何目录都可以使用nginx对应的相关命令。具体实现步骤如下:
演示可删除
/usr/local/nginx/sbin/nginx -V
cd /usr/local/nginx/sbin nginx -V
如何优化???
- 修改/etc/profile文件
vim /etc/profile
在最后一行添加
export PATH=$PATH:/usr/local/nginx/sbin
- 使之立即生效
source /etc/profile
- 执行nginx命令
nginx -V
(三)、Nginx静态资源部署
1.Nginx静态资源概述
上网去搜索访问资源对于我们来说并不陌生,通过浏览器发送一个HTTP请求实现从客户端发送请求到服务器端获取所需要内容后并把内容回显展示在页面的一个过程
。这个时候,我们所请 求的内容就分为两种类型,一类是静态资源、一类是动态资源。 静态资源即指在服务器端真实存在并且能直接拿来展示的一些文件,比如常见的html页面、css文件、js文件、图 片、视频等资源; 动态资源即指在服务器端真实存在但是要想获取需要经过一定的业务逻辑处理,根据不同的条件展示在页面不同这 一部分内容,比如说报表数据展示、根据当前登录用户展示相关具体数据等资源;
Nginx处理静态资源的内容,我们需要考虑下面这几个问题:
(1)静态资源的配置指令
(2)静态资源的配置优化
(3)静态资源的压缩配置指令
(4)静态资源的缓存处理
(5)静态资源的访问控制,包括跨域问题和防盗链问题
2.Nginx静态资源的配置指令
(1).listen指令
listen:用来配置监听端口。
listen的设置比较灵活,我们通过几个例子来把常用的设置方式熟悉下:
listen 127.0.0.1:8000; // listen localhost:8000 监听指定的IP和端口
listen 127.0.0.1; 监听指定IP的所有端口
listen 8000; 监听指定端口上的连接
listen *:8000; 监听指定端口上的连接
default_server属性是标识符,用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的address:port,则会默认执行的。如果不指定默认使用的是第一个server
。
# 假如说我们访问的的端口找不到,那么会默认指定第一个server
server {
listen 8080
server_name _;
default_type text/plain;
return 404 'not found server!!!';
}
server {
listen 8080;
server_name 127.0.0.1;
}
假如说我们找不到指定的主机和端口的话,会默认使用我们配置文件中第一个server的主机和端口!!!
# 查看行号vim编辑文本的行号
:set nu
# 从31-36行进行删除
:31,36d
假如说我们想使用我们自定义的主机和端口号该怎么做?
# 使用自定义的主机和端口号当作我们默认的
server {
listen 8080 default_server;
server_name 127.0.0.1;
}
(2).server_name指令
server_name:用来设置虚拟主机服务名称。
127.0.0.1 、 localhost 、域名[www.baidu.com | www.jd.com]
关于server_name的配置方式有三种,分别是:
精确匹配
通配符匹配
正则表达式匹配
配置方式一:精确匹配
如:
server {
listen 80;
server_name www.itcast.cn www.itheima.cn;
...
}
补充小知识点:
hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用
就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当
用户在浏览器中输入一个需要登录的网址时,系统会首先自动从hosts文
件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有
找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。
windows:C:\Windows\System32\drivers\etc
centos:/etc/hosts
因为域名是要收取一定的费用,所以我们可以使用修改hosts文件来制作一些虚拟域名来使用。需要修改 /etc/hosts文件来添加
vim /etc/hosts
127.0.0.1 www.itcast.cn
127.0.0.1 www.itheima.cn
配置方式二:使用通配符配置
server_name
中支持通配符 "*"
,但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段,如:
server {
listen 80;
server_name *.itcast.cn www.itheima.*;
# www.itcast.cn abc.itcast.cn www.itheima.cn www.itheima.com
}
下面的配置就会报错
server {
listen 80;
server_name www.*.cn www.itheima.c*
}
配置三:使用正则表达式配置
server_name中可以使用正则表达式,并且使用~作为正则表达式字符串的开始标记。
常见的正则表达式
server{
listen 80;
server_name ~^www\.(\w+)\.com$;
default_type text/plain;
return 200 $1 $2 ..;
}
注意 ~后面不能加空格,括号可以取值
(3).匹配执行顺序
由于 server_name
指令支持通配符和正则表达式,因此在包含多个虚拟主机的配置文件中,可能会出现一个名称被多个虚拟主机的server_name
匹配成功,当遇到这种情况,当前的请求交给谁来处理呢?
server{
listen 80;
server_name ~^www\.\w+\.com$;
default_type text/plain;
return 200 'regex_success';
}
server{
listen 80;
server_name www.itheima.*;
default_type text/plain;
return 200 'wildcard_after_success';
}
server{
listen 80;
server_name *.itheima.com;
default_type text/plain;
return 200 'wildcard_before_success';
}
server{
listen 80;
server_name www.itheima.com;
default_type text/plain;
return 200 'exact_success';
}
server{
listen 80 default_server;
server_name _;
default_type text/plain;
return 444 'default_server not found server';
}
结论:
exact_success
wildcard_before_success
wildcard_after_success
regex_success
default_server not found server!!
No1:准确匹配server_name
No2:通配符在开始时匹配server_name成功
No3:通配符在结束时匹配server_name成功
No4:正则表达式匹配server_name成功
No5:被默认的default_server处理,如果没有指定默认找第一个server
(4).location指令
server{
listen 80;
server_name localhost;
location / {
}
location /abc{
}
...
}
location:用来设置请求的URI
uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包含正则表达式进行匹配,找到一个匹配度最高
的一个,然后在通过包含正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚才匹配度最高的那个location来处理请求。
属性介绍:
- 不带符号,要求必须以指定模式开始
location /abc {
default_type text/plain;
return 200 'success 200';
}
我们得出结论,并不是精准匹配而是进行查询匹配度最高的。
- = : 用于不包含正则表达式的uri前,必须与指定的模式精确匹配
location =/abc {
default_type text/plain;
return 200 'success 200';
}
可以匹配到: http://8.130.48.9/abc
不可以匹配到: http://8.130.48.9/abcd
- ~ : 用于表示当前uri中包含了正则表达式,并且区分大小写。
~*: 用于表 示当前uri中包含了正则表达式,并且不区分大小写。
换句话说,如果uri包含了正则表达式,需要用上述两个符合来标识
server {
listen 80;
server_name 127.0.0.1;
location ~^/abc\w${
default_type text/plain;
return 200 "access success";
}
}
server {
listen 80;
server_name 127.0.0.1;
location ~*^/abc\w${
default_type text/plain;
return 200 "access success";
}
}
- ^~: 用于不包含正则表达式的uri前,功能和不加符号的一致,唯一不同的是,如果模式匹配,那么就停止搜索其他模式了。
如果我们在非正则表达式的前面添加了 ^~
如果找到第一个非正则表达式URL高精度的数值,就不会往下面找是否还有正则表达式的URL了。
server {
listen 80;
server_name 127.0.0.1;
location ^~/abc{
default_type text/plain;
return 200 "access success";
}
}
默认情况下先访问非正则URL,非正则访问完毕之后访问正则URL。如果能匹配到正则就是用正则。 ^~ 避免使用了正则,只使用非正则!!!
。
(5).设置请求资源的目录root / alias
这里的默认路径是与 nginx 的conf目录同级的。
- root:设置请求的根目录
- path为Nginx服务器接收到请求以后查找资源的根目录路径。
alias:用来更改location的URI
path为修改后的根路径。
以上两个指令都可以来指定访问资源的路径,那么这两者之间的区别是什么?
举例说明:
(1)在/usr/local/nginx/html目录下创建一个 images
目录,并在目录下放入一张图片 mv.jpg
图片.
location /images {
root /usr/local/nginx/html;
}
访问图片的路径为:
http://8.130.48.9/images/mv.jpg
我们发现访问这个路径之后,我们能访问到我们的图片。
(2)如果把root改为alias
location /images {
alias html;
}
再次访问上述地址,页面会出现404的错误,查看错误日志会发现是因为地址不对,所以验证了:
http://8.130.48.9/images/mv.jpg
root的处理结果是: root路径+location路径 (相当于 html +浏览器输入的url路径)
/usr/local/nginx/html/images/mv.png
alias的处理结果是:使用alias路径替换location路径 (相当于 html + 浏览器的最后一个参数)
/usr/local/nginx/html/mv.png
解决办法: 需要在alias后面路径改为
location /images {
alias /usr/local/nginx/html/images;
}
http://8.130.48.9/images/mv.jpg
(3)如果location路径是以/结尾
,则alias也必须是以/结尾
,root没有要求
将上述配置修改为
location /images/ {
alias /usr/local/nginx/html/images;
}
我们发现的问题是: 进行合并了!!!
访问就会出问题,查看错误日志还是路径不对,所以需要把alias后面加上 /
我们发现能访问到:
http://8.130.48.9/images/mv.jpg
小结:
root的处理结果是: root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的含义。
如果location路径是以/结尾,则alias也必须是以/结尾,root没有要求
(6).index指令 (指定默认在哪)
index:设置网站的默认首页
index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找,找到第一个为止。
举例说明:
location /images/ {
alias html/images/;
index mv.jpg;
}
访问该location的时候,可以通过 http://8.130.48.9/images,地址后面如果
不添加任何内容,则默认依次访问mv.jpg,找到第一个来进行返回
(7).error_page指令
error_page:设置网站的错误页面
当出现对应的响应code后,如何来处理。
举例说明:
(1)可以指定具体跳转的地址
server {
error_page 404 http://www.itcast.cn;
}
(2)可以指定重定向地址
server{
error_page 404 /50x.html;
error_page 500 502 503 504 /50x.html;
location =/50x.html{
root html;
}
}
(3)使用location的@符号 完成错误信息展示
server{
error_page 404 @jump_to_error;
location @jump_to_error {
default_type text/plain;
return 404 'Not Found Page...';
}
}
(4) 可选项=[response]的作用是用来将相应代码更改为另外一个
server{
error_page 404 =200 /50x.html;
location =/50x.html{
root html;
}
}
这样的话,当返回404找不到对应的资源的时候,在浏览器上可以看到,
最终返回的状态码是200,这块需要注意下,编写error_page后面的内
容,404后面需要加空格,200前面不能加空格
比如说假如报错出现404,我们就可以奖状态码更改成200.
3.静态资源优化配置语法
Nginx对静态资源如何进行优化配置。这里从三个属性配置进行优化:
sendfile on;
tcp_nopush on;
tcp_nodeplay on;
(1).sendfile,用来开启高效的文件传输模式。
请求静态资源的过程:客户端通过网络接口向服务端发送请求,操作系统将这些客户端的请求传递给服务器端应用程序,服务器端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。
如:
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html;
}
}
使用sendfile的处理流程: 2次copy且避免了用户态和内核的交换
未使用sendfile的处理流程: 4次copy和1次read和1次write
(2).tcp_nopush:该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输’效率’
(3).tcp_nodelay:该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的’实时性’
经过刚才的分析,“tcp_nopush"和”tcp_nodelay“看起来是"互斥的”,那么为什么要将这两个值都打开,这个大家需要知道的是在linux2.5.9以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前数据包已经充分“填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数, 然后,tcp_nodelay强制套接字发送数据。由此可知,TCP_NOPUSH可以与TCP_NODELAY一起设置,它比单独配置TCP_NODELAY具有更强的性能。所以我们可以使用如下配置来优化Nginx静态资源的处理
4.Nginx静态资源压缩实战
切记需要进行缓存的关闭处理
经过上述内容的优化,我们再次思考一个问题,假如在满足上述优化的前提下,我们传送一个1M的数据和一个10M的数据那个效率高?,答案显而易见,传输内容小,速度就会快。那么问题又来了,同样的内容,如果把大小降下来,我们脑袋里面要蹦出一个词就是"压缩",接下来,我们来学习Nginx的静态资源压缩模块。
在Nginx的配置文件中可以通过配置gzip来对静态资源进行压缩,相关的指令可以配置在http块、server块和location块中,Nginx可以通过对这些指令进行解析和处理。
ngx_http_gzip_module模块
ngx_http_gzip_static_module模块
ngx_http_gunzip_module模块
接下来我们从以下内容进行学习
(1)Gzip各模块支持的配置指令
(2)Gzip压缩功能的配置
(3)Gzip和sendfile的冲突解决
(4)浏览器不支持Gzip的解决方案
(1).Gzip模块配置指令
接下来所学习的指令都来自ngx_http_gzip_module模块,该模块会在nginx安装的时候内置到nginx的安装环境中,也就是说我们可以直接使用这些指令。
尚未开启压缩之前:
- gzip指令:该指令用于开启或者关闭gzip功能
注意只有该指令为打开状态,下面的指令才有效果
http{
gzip on;
}
- gzip_types指令:该指令可以根据响应页的MIME类型选择性地开启Gzip压缩功能
因为默认值text/html,但是我们请求的时候应该是 application/javaScript
;
如果我们想要生效的话,我们需要配置 nginx.conf
http{
gzip_types application/javascript;
gizp_types *; // 假如配置一个*,相当于对所有的类型都要进行压缩。浪费CPU资源
}
- gzip_comp_level指令:该指令用于设置Gzip压缩程度,级别从1-9,1表示要是程度最低,要是效率最高,9刚好相反,压缩程度最高,但是效率最低最费时间。
http{
gzip_comp_level 6;
}
- gzip_vary指令:该指令用于设置使用Gzip进行压缩发送是否携带“Vary:Accept-Encoding”头域的响应头部。主要是告诉接收方,所发送的数据经过了Gzip压缩处理
- gzip_buffers指令:该指令用于处理请求压缩的缓冲区数量和大小。
其中number: 指定Nginx服务器向系统申请缓存空间个数
,size 指的是每个缓存空间的大小
。主要实现的是申请number个每个大小为size的内存空间。这个值的设定一般会和服务器的操作系统有关,所以建议此项不设置,使用默认值即可。
gzip_buffers 4 16K; #缓存空间大小
- gzip_disable指令:针对不同种类客户端发起的请求,
可以选择性地开启和关闭Gzip功能
。
regex: 根据客户端的浏览器标志(user-agent)来设置
,支持使用正则表达式。指定的浏览器标志不使用Gzip.该指令一般是用来排除一些明显不支持Gzip的浏览器。
gzip_disable "MSIE [1-6]\.";
设置之后,就相当于这个不再使用压缩的操作!!!!
- gzip_http_version指令:针对不同的HTTP协议版本,可以选择性地开启和关闭Gzip功能。
该指令是指定使用Gzip的HTTP最低版本,该指令一般采用默认值即可。
- gzip_min_length指令:该指令针对传输数据的大小,可以选择性地开启和关闭Gzip功能
默认是 假如说大于20就不会进行压缩了。
nignx计量大小的单位:bytes[字节] / kb[千字节] / M[兆]
例如: 1024 / 10k|K / 10m|M
Gzip压缩功能对大数据的压缩效果明显,但是如果要压缩的数据比较小的化,可能出现越压缩数据量越大的情况,因此我们需要根据响应内容的大小来决定是否使用Gzip功能,响应页面的大小可以通过头信息中的Content-Length来获取。但是如何使用了Chunk编码动态压缩,该指令将被忽略。建议设置为1K或以上。
- gzip_proxied指令:该指令设置是否对服务端返回的结果进行Gzip压缩。
off - 关闭Nginx服务器对后台服务器返回结果的Gzip压缩 expired - 启用压缩,如果header头中包含 “Expires” 头信息 no-cache - 启用压缩,如果header头中包含 “Cache-Control:no-cache” 头信息 no-store - 启用压缩,如果header头中包含 “Cache-Control:no-store” 头信息 private -启用压缩,如果header头中包含 “Cache-Control:private” 头信息no_last_modified - 启用压缩,如果header头中不包含 “Last-Modified"头信息 no_etag - 启用压缩 ,如果header头中不包含 “ETag” 头信息 auth- 启用压缩 , 如果header头中包含"Authorization” 头信息 any - 无条件启用压缩
(2).Gzip压缩功能的实例配置
gzip on; #开启gzip功能
gzip_types *; #压缩源文件类型,根据具体的访问资源类型设定
gzip_comp_level 6; #gzip压缩级别
gzip_min_length 1024; #进行压缩响应页面的最小长度,contentlength
gzip_buffers 4 16K; #缓存空间大小
gzip_http_version 1.1; #指定压缩响应所需要的最低HTTP请求版本
gzip_vary on; #往头信息中添加压缩标识
gzip_disable "MSIE [1-6]\."; #对IE6以下的版本都不进行压缩
gzip_proxied off; #nginx作为反向代理压缩服务端返回数据的条件
这些配置在很多地方可能都会用到,所以我们可以将这些内容抽取到一个配置文件中,然后通过include指令把配置文件再次加载到nginx.conf配置文件中,方法使用。
nginx_gzip.conf
gzip on;
gzip_types *;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_buffers 4 16K;
gzip_http_version 1.1;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_proxied off;
nginx.conf
include nginx_gzip.conf
(3).Gzip和sendfile共存问题 (测试压缩成功✅)
前面在讲解sendfile的时候,提到过,开启sendfile以后,在读取磁盘上的静态资源文件的时候,可以减少拷贝的次数,可以不经过用户进程将静态文件通过网络设备发送出去,但是Gzip要想对资源压缩,是需要经过用户进程进行操作的
。所以如何解决两个设置的共存问题。可以使用ngx_http_gzip_static_module模块的gzip_static指令来解决。
- gzip_static指令
gzip_static: 检查与访问资源同名的.gz文件时,response中以gzip相关的header返回.gz文件的内容。
添加上述命令后,会报一个错误,unknown directive "gzip_static"主要的原因是Nginx默认是没有添加 ngx_http_gzip_static_module模块。如何来添加?
这里的gzip可以开启也可以不开启都可以成功,重点是gzip_static。
- 添加模块到Nginx的实现步骤
(1)查询当前Nginx的配置参数
nginx -V
先把旧的配置文件给复制下来....
--prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock
(2)将nginx安装目录下sbin目录中的nginx二进制文件进行更名
cd /usr/local/nginx/sbin
mv nginx nginxold
(3) 进入Nginx的安装目录
cd /root/nginx/core/nginx-1.16.1
(4)执行make clean清空之前编译的内容
make clean
(5)使用configure来配置参数
需要添加的模块是:
./configure --with-http_gzip_static_module
只需要执行我们这个完整配置
./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock --with-http_gzip_static_module
(6)使用make命令进行编译
make
(7) 将objs目录下的nginx二进制执行文件移动到nginx安装目录下的sbin目录中
mv objs/nginx /usr/local/nginx/sbin
(8)执行更新命令
make upgrade
- gzip_static测试使用
(1)直接访问
http://8.130.48.9/jquery-3.6.1.js
(2)使用gzip命令进行压缩
cd /usr/local/nginx/html
gzip jquery.js
(3)再次访问 http://8.130.48.9/jquery-3.6.1.js
5.静态资源的缓存处理
(1).什么是缓存
缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。
(2).什么是web缓存
Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求
。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页.
(3).web缓存的种类
客户端缓存
浏览器缓存
服务端缓存
Nginx / Redis / Memcached等
(4).浏览器缓存
是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览.
(5).为什么要用浏览器缓存
- 成本最低的一种缓存实现
- 减少网络带宽消耗
- 降低服务器压力
- 减少网络延迟,加快页面打开速度
(6).浏览器缓存的执行流程
HTTP协议中和页面缓存相关的字段,我们先来认识下:
(1)用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对应的缓存,所以需要发送request请求来获取数据
;
(2)服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,返回200的成功状态码并且在响应头上附上对应资源以及缓存信息
;
(3)当用户再次访问相同资源
的时候,客户端会在浏览器的缓存目录中查找是否存在响应的缓存文件
。
(4)如果没有找到对应的缓存文件,则走(2)步
。
(5)如果有缓存文件
,接下来对缓存文件是否过期进行判断,过期的判断标准是(Expires)。
(6)如果没有过期
,则直接从本地缓存中返回数据进行展示 (强缓存: 不需要经过两次验证,直接从缓存中拿)。
(7)如果Expires过期
,接下来需要判断缓存文件是否发生过变化
(8)判断的标准两个响应头是否同时存在且一致,一个是ETag(Entity Tag)
,一个是Last-Modified
。
(9)两个响应头判断结果是未发生变化,则服务端返回304 (not Modifed),直接从缓存文件中获取数据。(弱缓存: 需要先经过两次验证,然后从缓存中取)
(10)两个响应头判断发生了变化,重新从服务端获取数据 (200状态码),并根据缓存协商(服务端所设置的是否需要进行缓存数据的设置)来进行数据缓存
。
1.首先关闭浏览器缓存,并且模仿我们的第一次访问 200
2.然后打开浏览器缓存,记录状态码为 200 的响应头
3.然后打开浏览器缓存,尝试获取强缓存 304 并记录304的响应头
(7).浏览器缓存相关指令
Nginx需要进行缓存相关设置,就需要用到如下的指令
expires指令
expires: 该指令用来控制页面缓存的作用。可以通过该指令控制HTTP响应头中的Expires和Cache-Contro
- time:
可以整数也可以是负数
,指定过期时间,如果是负数,Cache-Control则为no-cache(也就是没缓存,关闭缓存的,每次网络请求都需要进行重新访问服务器)。如果为整数或0,则Cache-Control的值为max-age=time; - epoch: 指定Expires的值为’1 January,1970,00:00:01 GMT’(1970-01-01 00:00:00),Cache-Control的值no-cache
- max: 指定Expires的值为’31 December2037 23:59:59GMT’ (2037-12-31 23:59:59) ,Cache-Control的值为10年
- off:默认不缓存。
1.将我们的过期时间设置成正数: 响应头就会显示我们的时间
2.将我们的过期时间设置成负数: 那么响应头就会出现no-cache
3.设置成我们的 max,响应头为 3156310000。
add_header指令
add_header指令是用来添加指定的响应头和响应值。
Cache-Control作为响应头信息,可以设置如下值:
缓存响应指令:
Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
max-age=[秒]:
6.Nginx的跨域问题解决
这块内容,我们主要从以下方面进行解决:
什么情况下会出现跨域问题?
实例演示跨域问题
具体的解决方案是什么?
(1).同源策略
浏览器的同源策略:是一种约定,是浏览器最核心也是最基本的安全功能,如果浏览器少了同源策略,则浏览器的正常功能可能都会受到影响。
同源: 协议
、域名(IP)
、端口
相同即为同源。
http://192.168.200.131/user/1
https://192.168.200.131/user/1
不满足: 因为协议不一样
http://192.168.200.131/user/1
http://192.168.200.132/user/1
不满足: 因为IP不一样
http://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
不满足: 因为端口不一样
http://www.nginx.com/user/1
http://www.nginx.org/user/1
不满足: 因为域名不一样
http://www.nginx.org:80/user/1
http://www.nginx.org/user/1
满足: 协议、域名和端口都一样
(2).跨域问题
简单描述下:
有两台服务器分别为A,B。如果从服务器A
的页面发送异步请求到服务器B
获取数据,如果服务器A和服务器B不满足同源策略,则就会出现跨域问题。
(3).跨域问题的案例演示
出现跨域问题会有什么效果?,接下来通过一个需求来给大家演示下:
因为我们只有一台服务器所以我们只能通过改变端口来实现跨域问题!!!
(1)nginx的html目录下新建一个a.html
在8.130.48.9:80端口中部署一下页面
<html>
<head>
<meta charset="utf-8">
<title>跨域问题演示</title>
<script src="jquery.js"></script>
<script>
$(function(){
$("#btn").click(function(){
$.get('http://8.130.48.9:8081/getUser',function(data){
alert(JSON.stringify(data));
});
});
});
</script>
</head>
<body>
<input type="button" value="获取数据"id="btn"/>
</body>
</html>
(2)在nginx.conf配置如下内容
server{
listen 8081;
server_name localhost;
location /getUser{
default_type application/json;
return 200 '{"id":1,"name":"TOM","age":18}';
}
}
server{
listen 80;
server_name localhost;
location /{
root html;
index index.html;
}
}
(3).通过浏览器访问测试
直接访问8081端口得到数据: http://8.130.48.9:8081/getUser
访问80端口我们尝试获取跨域(8081)的值: http://8.130.48.9/a.html
结果报错了: 提示跨域出现问题
(4).解决跨域问题的具体实现
我们发现问题是缺少一个消息头: Access-Control-Allow-Origin
- 使用add_header指令,该指令可以用来添加一些头信息
此处用来解决跨域问题,需要添加两个头信息,一个是Access-Control-Allow-Origin
, Access-Control-Allow-Methods
。
Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息(也就是80),可以配置多个(多个用逗号分隔),也可以使用*代表所有源
。
Access-Control-Allow-Methods: 直译过来是允许跨域访问的请求方式,值可以为 GET POST PUT DELETE…,可以全部设置,也可以根据需要设置,多个用逗号分隔。
- 具体配置方式
1.我们需要在被请求的服务器(8081)上配置消息头,支持跨域。
location /getUser{
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
default_type application/json;
return 200 '{"id":1,"name":"TOM","age":18}';
}
查看我们的响应头: http://8.130.48.9:8081/getUser
- 测试我们的跨域
进行测试: http://8.130.48.9/a.html
7.静态资源防盗链
(1).什么是资源盗链
资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别人的限制将别人的内容放到自己页面上最终展示给用户
。以此来盗取大网站的空间和流量。简而言之就是用别人的东西成就自己的网站。
效果演示
京东: https://img14.360buyimg.com/n7/jfs/t1/101062/37/2153/254169/5dcbd410E6d10ba22/4ddbd212be225fcd.jpg
百度:https://pics7.baidu.com/feed/cf1b9d16fdfaaf516f7e2011a7cda1e8f11f7a1a.jpeg?token=551979a23a0995e5e5279b8fa1a48b34&s=BD385394D2E963072FD48543030030BB
我们自己准备一个页面,在页面上引入这两个图片查看效果
从上面的效果,可以看出来,下面的图片地址添加了防止盗链的功能,京东这边我们可以直接使用其图片。
(2).Nginx防盗链的实现原理:
了解防盗链的原理之前,我们得先学习一个HTTP的头信息Referer, 当浏览器向web服务器发送请求的时候,一般都会带上Referer,来告诉浏览器该网页是从哪个页面链接过来的
。
后台服务器可以根据获取到的这个Referer信息来判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息
。
在本地模拟上述的服务器效果:
1.首先在html/images/下面添加我们的静态资源
2.在conf/nginx.conf (8081服务器)下配置我们的静态资源开放
3.在我们的a.html中添加一个图片
4.发现我们访问的时候能够正常访问 (可以正常展示)
http://8.130.48.9/a.html
Nginx防盗链的具体实现:
valid_referers
: nginx会通过查看referer
自动和valid_referers
后面的内容进行匹配。
- 如果匹配到了就将
$invalid_referer
变量置0。 - 如果没有匹配到,则将
$invalid_referer
变量置为1,匹配的过程中不区分大小写。
none: 如果Header中的 Referer为空,允许访问
。
blocked: 在Header中的Referer不为空
,但是该值被防火墙或代理进行伪装过,如不带"http://" 、"https://"等协议头的资源允许访问
。
server_names: 指定具体的域名或者IP
。
string: 可以支持正则表达式和*的字符串
。如果是正则表达式,需要以~开头表示,例如
我们在80端口出
location ~.*\.(png|jpg|gif)$ { # 这里也要与大括号进行空格的处理
valid_referers none blocked www.baidu.com ; #这里的意思是指: 允许www.baidu.com访问
if ($invalid_referer){ # 切记这个if与括号一定要有空格,且Nginx使用变量名的时候我们需要添加上一个 $ 符号
return 403;
}
root html/images;
}
(3).针对静态资源目录进行防盗链
- 配置如下:
我们要配置我们的 8081 的操作!!!
location /images { # 切记路径后面也要空格
root html;
valid_referers none blocked www.baidu.com;
if ($invalid_referer){ # 切记这个if与括号一定要有空格,且Nginx使用变量名的时候我们需要添加上一个 $ 符号
return 403;
}
}
1.因为我们更改了路径所以访问不到 :
http://8.130.48.9:8081/mv.jpg
- 我们直接访问(8081)能够成功
http://8.130.48.9:8081/images/mv.jpg
- 我们通过 80 进行跨域跳转不可以访问
http://8.130.48.9/a.html
- 加入我们将 8081 的静态资源对 8.130.48.9允许
我们发现我们运行成功!!!
http://8.130.48.9/a.html
这样我们可以对一个目录下的所有资源进行翻到了操作。
遇到的问题:Referer的限制比较粗,比如随意加一个Referer,上面的方式是无法进行限制的。
那么这个问题改如何解决?
此处我们需要用到Nginx的第三方模块ngx_http_accesskey_module
,第三方模块如何实现盗链,如果在Nginx中使用第三方模块的功能,这些我们在后面的Nginx的模块篇再进行详细的讲解。
8.Rewrite功能配置
Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是用来实现URL的重写
。
注意: Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库
。Nginx使用的是ngx_http_rewrite_module
模块来解析和处理Rewrite功能的相关配置。
(1).“地址重写"与"地址转发”
重写和转发的区别:
- 地址重写浏览器地址会发生变化而地址转发则不变
- 一次地址重写会产生两次请求而一次地址转发只会产生一次请求
- 地址重写到的页面必须是一个完整的路径而地址转发则不需要
- 地址重写因为是两次请求所以request范围内属性不能传递给新页面而地址转发因为是一次请求所以可以传递值
- 地址转发速度快于地址重写
(2).set指令
该指令用来设置一个新的变量。
切记在Nginx使用变量名的时候我们需要在前面添加一个$符号。
-
variable:
变量的名称,该变量名称要用"$"作为变量的第一个字符
,且不能与Nginx服务器预设的全局变量同名。 -
value: 变量的值,可以是字符串、其他变量或者变量的组合等。
#rewrite
server {
listen 8082;
server_name localhost;
location /server {
set $name JSXS; #设置变量name并赋值为JSXS
set $age 22; #设置变量age并赋值为22
default_type text/plain; # 设置我们的返回类型
return 200 $name-$age; # 设置我们的返回结果
}
}
http://8.130.48.9:8082/server
(3).Rewrite常用全局变量
我们使用这些变量可以进行自定义我们的日志格式
变量 | 说明 |
---|---|
$args | 变量中存放了请求URL中的请求指令。比如http://8.130.48.9:8082/server?arg1=value1&args2=value2中的"arg1=value1&arg2=value2 ",功能和$query_string一样 |
$http_user_agent | 变量存储的是用户访问服务的代理信息(如果通过浏览器访问,记录的是浏览器的相关版本信息 ) |
$host | 变量存储的是访问服务器的server_name值(IP地址 ) |
$document_uri | 变量存储的是当前访问地址的URI。比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server",功能和$uri一样 |
$document_root | 变量存储的是当前请求对应location的root值,如果未设置,默认指向Nginx自带html目录所在位置 |
$content_length | 变量存储的是请求头中的Content-Length的值 |
$content_type | 变量存储的是请求头中的Content-Type的值 |
$http_cookie | 变量存储的是客户端的cookie信息,可以通过add_header Set-Cookie’cookieName=cookieValue’来添加cookie数据 |
$limit_rate | 变量中存储的是Nginx服务器对网络连接速率的限制,也就是Nginx配置中对limit_rate指令设置的值,默认是0,不限制。 |
$remote_addr | 变量中存储的是客户端的IP地址 |
$remote_port | 变量中存储了客户端与服务端建立连接的端口号 |
$remote_user | 变量中存储了客户端的用户名,需要有认证模块才能获取 |
$scheme | 变量中存储了访问协议 |
$server_addr | 变量中存储了服务端的地址 |
$server_name | 变量中存储了客户端请求到达的服务器的名称 |
$server_port | 变量中存储了客户端请求到达服务器的端口号 |
$server_protocol | 变量中存储了客户端请求协议的版本,比如"HTTP/1.1" |
$request_body_file | 变量中存储了发给后端服务器的本地文件资源的名称 |
$request_method | 变量中存储了客户端的请求方式,比如"GET","POST"等 |
$request_filename | 变量中存储了当前请求的资源文件的路径名 |
$request_uri | 变量中存储了当前请求的URI,并且携带请求参数,比如http://8.130.48.9:8082/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan " |
- $args 变量: 存放URL里面的变量信息
#rewrite
server {
listen 8082;
server_name localhost;
location /server {
set $name JSXS;
set $age 22;
default_type text/plain;
return 200 $name-$age=$args;
}
}
- $http_user_agent: 浏览器的相关版本信息
- $host: 存储的是访问服务器的server_name
- $document_uri: 获取RESTFUL风格的路径
- $document_root: 静态资源根目录也就是 location下配置的root
(4).if指令
该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置。
condition为判定条件,可以支持以下写法:
- 变量名。如果
变量名对应的值为空或者是0
,if都判断为false,其他条件为true。
if ($param){ // if与小括号之间要有一个空格隔着
}
- 使用
"="和"!="
比较变量和字符串是否相等,满足条件为true,不满足为false
if ($request_method = POST){ //判断请求的方法是否是POST
return 405;
}
注意:此处和Java不太一样的地方是字符串不需要添加引号。
- 使用正则表达式进行判断是否包含某个值
- "~"代表匹配正则表达式过程中区分大小写,
- "~*"代表匹配正则表达式过程中不区分大小写
- "!~ “和”!~*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true
if ($http_user_agent ~ MSIE){ //$http_user_agent的值中是否包含MSIE字符串,如果包含返回true
}
注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含"}“或者是”;"等字符时,就需要把引号加上。
- 判断请求的文件是否存在 使用"-f"和"!-f"
- 当使用"-f"时,如果请求的文件存在返回true,不存在返回false。
- 当使用"!f"时,
如果请求文件不存在,但该文件所在目录存在返回true
,文件和目录都不存在返回false
,如果文件存在返回false
if (-f $request_filename){
//判断请求的文件是否存在
}
if (!-f $request_filename){
//判断请求的文件是否不存在
}
- 判断请求的目录是否存在使用"-d"和"!-d",
- 当使用 “-d” 时,如果请求的目录存在,if返回true,如果目录不存在则返回false。
- 当使用 “!-d” 时,如果请求的目录不存在但该目录的上级目录存在则返回true,该目录和它上级目录都不存在则返回false,如果请求目录存在也返回false。
- 判断请求的目录或者文件是否存在使用"-e"和"!-e"
- 当使用"-e",如果请求的目录或者文件存在时,if返回true,否则返回false.
- 当使用"!-e",如果请求的文件和文件所在路径上的目录都不存在返回true,否则返回false
- 判断请求的文件是否可执行使用"-x"和"!-x"
- 当使用"-x",如果请求的文件可执行,if返回true,否则返回false
- 当使用"!-x",如果请求文件不可执行,返回true,否则返回false
(5).break指令
该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效
。并且break还有另外一个功能就是终止当前的匹配并把当前的URL在本location进行重定向访问处理。
例子:
经过break之后,我们会发现会跳转到 http://8.130.48.9:8081/test
会找 html/test/index.html这个页面进行返回,如果找不到的话会去找404页面。
location /test {
if ($param){
set $id $1;
break;
limit_rate 10k;
}
}
(6).return指令
该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在return后的所有Nginx配置都是无效的。
code
: 为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理text
: 为返回给客户端的响应体内容,支持变量的使用URL
: 为返回给客户端的URL地址
(7).rewrite指令
该指令通过正则表达式的使用来改变URI
。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。
URL和URI的区别:
URI:统一资源标识符
URL:统一资源定位符
- regex:
用来匹配URI的正则表达式
- replacement:
匹配成功后,用于替换URI中被截取内容的字符串。如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端
。 - flag:
用来设置rewrite对URI的处理行为
,可选值有如下:-
last: 终止继续在本location块中处理接收到的URL,并将此处重写的URL,使用各location块进行处理。该标志将重写后的URL重写在server块中执行,为重写后的URL提供了转入到其他location块的机会。
我们在这里标志的是:last
-
break:
将此处重写的URL作为一个新的URL,在本块中继续进行处理
。该标志将重写后的地址在当前的location块中执行,不会将新的URL转向其他的location块。
-
redirect:
将重写的URL返回给客户端,状态码为302,指明的是临时重定向UR
L,主要用在replacement变量不是以"http://"
或者"https://"
开头的情况。
-
permanent: 将重写后的URL返回给客户端,状态码为301,指明是永久重定向URL,主要用在relacement变量不是以 “http://” 或者 "ttps://"开头的情况。
-
location /rewrite {
rewrite ^/rewrite/url\w*$ https://www.baidu.com; # 当开头是url的时候,我们会匹配到百度官网
rewrite ^/rewrite/(test)\w*$ /$1; # 当我们开头是test的时候,我们会跳转到 /test
rewrite ^/rewrite/(demo)\w*$ /$1; # 当我们的开头是demo的时候,我们会跳转到demo
}
location /test {
default_type text/plain;
return 200 test_success;
}
location /demo {
default_type text/plain;
return 200 demo_success;
}
- 跳转到百度
我们使用这个连接进行跳转: http://8.130.48.9:8081/rewrite/urlabc因为我们使用的是url匹配的
- 利用test的操作
利用test开头的: http://8.130.48.9:8081/rewrite/testdf
- 利用demo的操作
利用demo开头的: http://8.130.48.9:8081/rewrite/demofe
(8).rewrite_log指令
该指令配置是否开启URL重写日志的输出功能。
开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总。
rewrite_log on; # 开启日志
error_log logs/error.log notice; #设置日志格式
location /rewrite {
rewrite_log on; # 开启日志
error_log logs/error.log notice; #设置日志格式
rewrite ^/rewrite/url\w*$ https://www.baidu.com;
rewrite ^/rewrite/(test)\w*$ /$1 permanent;
rewrite ^/rewrite/(demo)\w*$ /$1 permanent;
}
location /test {
default_type text/plain;
return 200 test_success;
}
location /demo {
default_type text/plain;
return 200 demo_success;
}
9.Rewrite的案列
(1).域名跳转
先来看一个效果,如果我们想访问京东网站,大家都知道我们可以输入 www.jd.com
,但是同样的我们也可以输入 www.360buy.com
同样也都能访问到京东网站。 这个其实是因为京东刚开始的时候域名就是 www.360buy.com
,后面由于各种原因把自己的域名换成了 www.jd.com
, 虽然说域名变量,但是对于以前只记住了 www.360buy.com
的用户来说,我们如何把这部分用户也迁移到我们新域名的访问上来,针对于这个问题,我们就可以使用 Nginx中Rewrite的域名跳转来解决。
- 三个域名都可以访问同一个服务
- 准备三个域名
vim /etc/hosts
127.0.0.1 www.itcast.cn
127.0.0.1 www.itheima.cn
127.0.0.1 www.itheima.com
2. 通过Rewrite完成将www.ithema.com
和www.itheima.cn
的请求跳转到www.itcast.com
。
#rewrite case
server {
listen 8082;
server_name www.itcast.cn
location /{
default_type text/html;
return 200 '<h1>welcome to itcats</h1>';
}
}
我们配置完成之后,无论输入哪一个域名都会进行跳转到同一个server_name的内容。
- 三个域名都跳转到同一个域名且服务相同
server {
listen 8082;
server_name www.itheima.com www.itheima.cn;
rewrite ^/ http://www.itcast.cn;
}
- 问题描述:如何在域名跳转的过程中携带请求的URI?
server {
listen 8082 ;
server_name www.itheima.com www.itheima.cn;
rewrite ^(.*) http://www.itcast.cn$1;
}
(2).域名镜像
镜像网站指定是将一个完全相同的网站分别放置到几台服务器上,并分别使用独立的URL进行访问。其中一台服务器上的网站叫主站,其他的为镜像网站。镜像网站和主站没有太大的区别,可以把镜像网站理解为主站的一个备份节点。可以通过镜像网站提供网站在不同地区的响应速度。镜像网站可以平衡网站的流量负载、可以解决网络宽带限制、封锁等
。
而我们所说的域名镜像和网站镜像比较类似,上述案例中,将www.itheima.com
和 www.itheima.cn
都能跳转到 www.itcast.cn
,那么www.itcast.cn我们就可以把它起名叫主域名,其他两个就是我们所说的镜像域名,当然如果我们不想把整个网站做镜像,只想为其中某一个子目录下的资源做镜像,我们可以在location块中配置rewrite功能,比如:
server {
listen 80;
server_name www.itheima.cn www.itheima.com;
location /user {
# 匹配user后面的所有字符串
rewrite ^/user(.*)$ http://www.itcast.cn$1;
}
location /emp{
default_type text/html;
return 200 '<h1>emp_success</h1>';
}
}
(3).独立域名
一个完整的项目包含多个模块,比如购物网站有商品搜索模块、商品详情模块和购物车模块等,那么我们如何为每一个模块设置独立的域名。
需求:
http://search.itcast.com:81 访问商品搜索模块
http://item.itcast.com:82 访问商品详情模块
http://cart.itcast.com:83 访问商品购物车模块
server{
listen 81;
server_name search.itcast.com;
# 匹配域名之后的所有字符串
rewrite ^(.*) http://www.itcast.cn/search$1;
}
server{
listen 82;
server_name item.itcast.com;
rewrite ^(.*) http://www.itcast.cn/item$1;
}
server{
listen 83;
server_name cart.itcast.com;
rewrite ^(.*) http://www.itcast.cn/cart$1;
}
(4).目录自动添加"/"
问题描述
通过一个例子来演示下问题:
server{
listen 8082;
server_name localhost;
location /heima {
root html;
index index.html;
}
}
通过http://8.130.48.9:8082/heima/ 和http://8.130.48.9:8082/heima 通过访问的区别?
cd html
mkidr heima
cd heima/
echo '<h1>welcome to heima!!</h1>' > index.html
http://8.130.48.9:8082/heima
http://8.130.48.9:8082/heima/
如果不加斜杠,Nginx服务器内部会自动做一个301的重定向,重定向的地址会有一个指令叫 server_name_in_redirect on|off
; 来决定重定向的地址:
如果该指令为on
重定向的地址为: http://server_name:8082/目录名/;
http://localhost:8082/heima/
如果该指令为off
重定向的地址为: http://原URL中的域名:8082/目录名/;
http://192.168.200.133:8082/heima/
所以就拿刚才的地址来说,http://192.168.200.133:8082/heima如果不加斜杠,那么按照上述规则,如果指令server_name_in_redirect为on,则301重定向地址变为 http://localhost:8082/heima/,如果为off,则301重定向地址变为http://192.168.200.133:8082/heima/。后面这个是正常的,前面地址就有问题。
注意server_name_in_redirect指令在Nginx的0.8.48版本之前默认都是on,之后改成了off,所以现在我们这个版本不需要考虑这个问题,但是如果是0.8.48以前的版本并且server_name_in_redirect设置为on,我们如何通过rewrite来解决这个问题?
解决方案
我们可以使用rewrite功能为末尾没有斜杠的URL自动添加一个斜杠
server {
listen 8082;
server_name localhost;
server_name_in_redirect on;
location /heima {
if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/permanent;
}
}
}
(5).合并目录
搜索引擎优化(SEO)是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎内排名的方式
。我们在创建自己的站点时,可以通过很多中方式来有效的提供搜索引擎优化的程度。其中有一项就包含URL的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担,但是将所有的文件放在一个目录下又会导致文件资源管理混乱并且访问文件的速度也会随着文件增多而慢下来,这两个问题是相互矛盾的,那么使用rewrite如何解决上述问题?
举例,网站中有一个资源文件的访问路径时 /server/11/22/33/44/20.html
,也就是说 20.html
存在于第5级目录下,如果想要访问该资源文件,客户端的URL地址就要写成 http://192.168.200.133/server/11/22/33/44/20.html
。
server {
listen 8083;
server_name localhost;
location /server{
root html;
}
}
但是这个是非常不利于SEO搜索引擎优化的,同时客户端也不好记.使用 rewrite
我们可以进行如下配置:
server {
listen 8083;
server_name localhost;
location /server{
rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /server/$1/$2/$3/$4/$5.html last;
}
}
这样的话,客户端只需要输入 http://www.web.name/server-11-22-33-44-20.html
就可以访问到20.html页面了。这里也充分利用了rewrite指令支持正则表达式的特性。
(6).防盗链
防盗链之前我们已经介绍过了相关的知识,在rewrite中的防盗链和之前将的原理其实都是一样的,只不过通过rewrite可以将防盗链的功能进行完善下,当出现防盗链的情况,我们可以使用rewrite将请求转发到自定义的一张图片和页面,给用户比较好的提示信息。下面我们就通过根据文件类型实现防盗链的一个配置实例:
location /images {
root html;
valid_referers none blocked www.baidu.com;
if ($invalid_referer){
#return 403;
rewrite ^/ /images/forbidden.png break;
}
}
(四)、Nginx反向代理
1.Nginx反向代理概述
关于正向代理和反向代理,我们在前面的章节已经通过一张图给大家详细的介绍过了,简而言之就是正向代理代理的对象是客户端,反向代理代理的是服务端,这是两者之间最大的区别。
Nginx即可以实现正向代理,也可以实现反向代理。
我们先来通过一个小案例演示下Nginx正向代理的简单应用。
先提需求:
2.Nginx反向代理的配置语法
Nginx反向代理模块的指令是由 ngx_http_proxy_module
模块进行解析,该模块在安装Nginx的时候已经自己加装到Nginx中了,接下来我们把反向代理中的常用指令一一介绍下:
proxy_pass
proxy_set_header
proxy_redirect
(1).proxy_pass
该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。
URL: 为要设置的被代理服务器地址,包含传输协议( http , https:// )、主机名称或IP地址加端口号、URI等要素。
server {
listen 8081;
server_name localhost;
location / {
# 假如我们访问localhost:8081,那么就会反向代理到百度
proxy_pass http://www.baidu.com;
}
}
大家在编写proxy_pass的时候,后面的值要不要加"/"?
接下来通过例子来说明刚才我们提到的问题:
server {
listen 80;
server_name localhost;
location /{
#proxy_pass http://192.168.200.146;
proxy_pass http://192.168.200.146/;
}
}
# 当客户端访问 http://localhost/index.html,效果是一样的
server{
listen 80;
server_name localhost;
location /server{
#proxy_pass http://192.168.200.146;
proxy_pass http://192.168.200.146/;
}
}
# 当客户端访问 http://localhost/server
第一个proxy_pass就变成了 http://localhost/server/index.html。(会将路径/server进行拼接到后面)
第二个proxy_pass就变成了http://localhost/index.html。(不会讲路径/server进行拼接到后面)
总结: 假如我们proxy_pass后面代理的路径末尾加了/,就不会进行拼接location块后的路径,假如没有拼接那么将会 location 块中的路径进行拼接到我们的反向代理的路径中去。
(2).proxy_set_header
该指令可以更改Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给代理的服务器.
需要注意的是,如果想要看到结果,必须在被代理的服务器上来获取添加的头信息。
被代理服务器: [192.168.200.146]
server {
listen 8080;
server_name localhost;
location /{
default_type text/plain;
return 200 $http_username;
}
}
代理服务器: [192.168.200.133]
server {
listen 8080;
server_name localhost;
location /server {
proxy_pass http://192.168.200.146:8080/;
proxy_set_header username TOM;
}
}
访问: http://192.168.200.133/server 我们看到的返回tom值
(3).proxy_redirect
该指令是用来重置头信息中的"Location"和"Refresh"的值。
为什么要用该指令?
服务端[192.168.200.146]
server {
listen 8081;
server_name localhost;
if (!-f $request_filename){ # 假如说请求的文件不存在,那么就进行重定向
return 302 http://192.168.200.146;
}
}
代理服务端[192.168.200.133] -> (客户端访问代理服务端)
server {
listen 8081;
server_name localhost;
location / {
proxy_pass http://192.168.200.146:8081/;
# 重定向地址:
proxy_redirect http://192.168.200.146 http://192.168.200.133;
}
}
我们找不到文件之后,会重定向到被代理服务器。这样的话被代理服务器的IP就暴漏的,这样是非常不安全的!!!
我们使用这个 proxy_redirect 就可以实现安全机制
# 重定向地址: 重定向的代理服务器 在跳转到哪里
proxy_redirect http://192.168.200.146 http://192.168.200.133;
该指令的几组选项
proxy_redirect redirect replacement;
redirect: 目标,Location的值
replacement: 要替换的值
proxy_redirect default;
default;
将location块的uri变量作为replacement,
将proxy_pass变量作为redirect进行替换
proxy_redirect off;
关闭proxy_redirect的功能
3.Nginx反向代理实战
(1).代理的服务器内容不同
服务器1,2,3存在两种情况
第一种情况: 三台服务器的内容不一样。
第二种情况: 三台服务器的内容是一样。
- 如果服务器1、服务器2和服务器3的内容不一样,那我们可以根据用户请求来分发到不同的服务器。
# 代理服务器 ⭐
server {
listen 80;
server_name localhost;
location /server1 {
proxy_pass http://192.168.200.146:9001/;
}
location /server2 {
proxy_pass http://192.168.200.146:9002/;
}
location /server3 {
proxy_pass http://192.168.200.146:9003/;
}
}
#服务端 ⭐
# server1
server {
listen 9001;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.200.146:9001</h1>'
}
# server2
server {
listen 9002;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.200.146:9002</h1>'
}
# server3
server {
listen 9003;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.200.146:9003</h1>'
}
- 代理服务端配置
- 服务端配置
4. 测试
(2).代理的服务器内容相同
负载均衡
4.Nginx的安全控制
关于web服务器的安全是比较大的一个话题,里面所涉及的内容很多,Nginx反向代理是如何来提升web服务器的安全呢?
安全隔离
什么是安全隔离?
通过代理分开了客户端到应用程序服务器端的连接,实现了安全措施。在反向代理之前设置防火墙,仅留一个入口供代理服务器访问。
(1).如何使用SSL对流量进行加密
翻译成大家能熟悉的说法就是将我们常用的 http请求转变成https请求,那么这两个之间的区别简单的来说两个都是HTTP协议,只不过https是身披SSL外壳的http.
HTTPS是一种通过计算机网络进行安全通信的传输协议。它经由HTTP进行通信,利用SSL/TLS建立全通信,加密数据包,确保数据的安全性。
-
SSL(Secure Sockets Layer) 安全套接层
-
TLS(Transport Layer Security) 传输层安全
上述这两个是为网络通信提供安全及数据完整性的一种安全协议,TLS和SSL在传输层和应用层对网络连接进行加密。
总结来说为什么要使用https:
http协议是明文传输数据,存在安全问题,而https是加密传输,相当于
http+ssl
,并且可以防止流量劫持
。
Nginx要想使用SSL,需要满足一个条件即需要添加一个模块--with_http_ssl_module
,而该模块在编译的过程中又需要OpenSSL的支持,这个我们之前已经准备好了。 默认时没有添加支持这个模块的!!!
(2).nginx添加SSL的支持
- 完成
--with-http_ssl_module
模块的增量添加
我们刚开始的时候已经添加了对应个模块
》将原有/usr/local/nginx/sbin/nginx进行备份
》拷贝nginx之前的配置信息
》在nginx的安装源码进行配置指定对应模块 ./configure --
with-http_ssl_module
》通过make模板进行编译
》将objs下面的nginx移动到/usr/local/nginx/sbin下
》在源码目录下执行 make upgrade进行升级,这个可以实现不停机添
加新模块的功能
# 1.进入可执行文件 ⭐
cd /usr/local/nginx/sbin
# 2.查看之前有哪些配置 ⭐
./nginx -V
[root@Jsxs sbin]# ./nginx -V
nginx version: nginx/1.16.1
built by gcc 10.2.1 20200825 (Alibaba 10.2.1-3.5 2.32) (GCC)
configure arguments: --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock --with-http_gzip_static_module
# 3.复制粘贴我们的配置 ⭐
--prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock --with-http_gzip_static_module
# 4.
mv nginx nginxold
# 5.回到我们的安装包目录
cd ~/nginx/core/nginx-1.16.1/
# 6. 把3复制的粘贴回来,并在末尾添加 --with-http_ssl_module
./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock --with-http_gzip_static_module --with-http_ssl_module
# 7.执行make编译,在objs目录中产生可执行文件
cd /root/nginx/core/nginx-1.16.1/objs
# 8.查看是否生成
ll
# 9.将objs新生成的可执行文件移动到sbin
cp nginx /usr/local/nginx/sbin/
# 10. 回跳到上一层
cd /root/nginx/core/nginx-1.16.1
# 11. 执行平滑升级
make upgrade
# 12. 查看是否添加成功
nginx -V
(3).Nginx的SSL相关指令
因为刚才我们介绍过该模块的指令都是通过 ngx_http_ssl_module
模块来解析的。
- SSL
ssl: 该指令用来在指定的服务器开启HTTPS,可以使用 listen 443 ssl,后面这种方式更通用些。
server{
listen 443 ssl;
}
- ssl_certificate
ssl_certificate: 为当前这个虚拟主机指定一个带有 PEM格式证书
的证书
- ssl_certificate_key
ssl_certificate_key:该指令用来指定 PEM secret key
文件的路径
- ssl_session_cache
ssl_session_cache:该指令用来配置用于SSL会话的缓存
- off: 禁用会话缓存,客户端不得重复使用会话
- none: 禁止使用会话缓存,客户端可以重复使用,但是并没有在缓存中存储会话参数
- builtin: 内置OpenSSL缓存,仅在一个工作进程中使用。
- shared: 所有工作进程之间共享缓存,缓存的相关信息用name和size来指定
- ssl_session_timeout
ssl_session_timeout:开启SSL会话功能后,设置客户端能够反复使用储存在缓存中的会话参数时间。
- ssl_ciphers
ssl_ciphers:指出允许的密码,密码指定为OpenSSL支持的格式
可以使用openssl ciphers查看openssl支持的格式。
- ssl_prefer_server_ciphers
ssl_prefer_server_ciphers:该指令指定是否服务器密码优先客户端密码
(4).生产证书
- 使用阿里云第三方购买
https://yundun.console.aliyun.com
- 方式二: 使用openssl生成证书
先确认当前系统是否有安装openssl
openssl version
安装下面的命令进行生成
mkdir /root/cert
cd /root/cert
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey
server.key -out server.crt
(5).开启SSL实列
server {
# 默认端口是 443
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;
}
}
(6).将指定项目设置成https
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /root/cert/9350134_www.jsxs1.cn.pem;
ssl_certificate_key /root/cert/9350134_www.jsxs1.cn.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://8.130.48.9:8181/;
}
}
5.反向代理系统调优
反向代理值Buffer和Cache
Buffer翻译过来是"缓冲",Cache翻译过来是"缓存"。
总结下:
- 相同点:
- 两种方式都是用来提供IO吞吐效率,都是用来提升Nginx代理的性能。
- 不同点:
- 缓冲主要用来解决不同设备之间数据传递速度不一致导致的性能低的问题,缓冲中的数据一旦此次操作完成后,就可以删除。
- 缓存主要是备份,将被代理服务器的数据缓存一份到代理服务器,这样的话,客户端再次获取相同数据的时候,就只需要从代理服务器上获取,效率较高,缓存中的数据可以重复使用,只有满足特定条件才会删除.
(1).Proxy Buffer相关指令
- proxy_buffering
proxy_buffering :该指令用来开启或者关闭代理服务器的缓冲区;
- proxy_buffers
proxy_buffers:该指令用来指定单个连接从代理服务器读取响应的缓存区的个数和大小。
number:缓冲区的个数
size:每个缓冲区的大小,缓冲区的总大小就是number*size
- proxy_buffer_size
proxy_buffer_size:该指令用来设置从被代理服务器获取的第一部分响应数据的大小。保持与proxy_buffers中的size一致即可,当然也可以更小。
- proxy_busy_buffers_size
proxy_busy_buffers_size:该指令用来限制同时处于BUSY状态的缓冲总大小。
- proxy_temp_path
proxy_temp_path:当缓冲区存满后,仍未被Nginx服务器完全接受,响应数据就会被临时存放在磁盘文件上,该指令设置文件路径
注意path最多设置三层。
- proxy_temp_file_write_size
proxy_temp_file_write_size:该指令用来设置磁盘上缓冲文件的大小。
通用网站的配置
proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;