nginx笔记
常用配置(直接复制吧)
是否需要加斜杠
安装所需包
./configure --prefix=/usr/local/nginx --with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_gunzip_module \
--with-stream \
--with-stream_ssl_moduleevent块
events{
#设置Nginx网络连接序列化
accept_mutex on;
#设置Nginx的worker进程是否可以同时接收多个请求
multi_accept on;
#设置Nginx的worker进程最大的连接数
worker_connections 1024;
#设置Nginx使用的事件驱动模型
use epoll;
}静态资源优化配置
sendfile on;
tcp_nopush on;
tcp_nodeplay on;资源防盗链
valid_referers 外网ip 域名;
# 如果不是白名单则 显示403 禁止访问
if ($invalid_referer) {
return 403;
}gizp
#新建一个nginx_gzip.conf配置文件, 然后将其include即可
gzip on; #开启gzip功能
gzip_types *; #压缩源文件类型,根据具体的访问资源类型设定
gzip_comp_level 6; #gzip压缩级别
gzip_min_length 1024; #进行压缩响应页面的最小长度,content-length
gzip_buffers 4 16K; #缓存空间大小
gzip_http_version 1.1; #指定压缩响应所需要的最低HTTP请求版本
gzip_vary on; #往头信息中添加压缩标识
gzip_disable "MSIE [1-6]\."; #对IE6以下的版本都不进行压缩
gzip_proxied off; #nginx作为反向代理压缩服务端返回数据的条件注意:需要下述模块才能使用
# Nginx可以通过对这些指令进行解析和处理。
ngx_http_gzip_module模块 (这个模块默认有了)
ngx_http_gzip_static_module模块
ngx_http_gunzip_module模块反向代理调优(通用网站的配置)
proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;七层负载均衡配置
upstream backend{
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}四层负载均衡配置
stream {
upstream redisbackend {
server 192.168.111.128:6379;
server 192.168.111.128:6378;
}
upstream tomcatbackend {
server 192.168.111.128:8080;
}
server {
listen 81;
proxy_pass redisbackend;
}
server {
listen 82;
proxy_pass tomcatbackend;
}
}只允许用域名访问
if ($host !~* ^(?:www\.bzlan\.net\.cn)$){
return 404;
}官网
https://nginx.org/en/
# 如需下载低版本,请用下方地址
http://nginx.org/download/Nginx的功能特性及常用功能
基本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代理服务功能
Nginx常用的功能模块

Nginx的核心组成
环境准备
准备一个内核为2.6及以上版本的操作系统
- linux2.6及以上内核才支持epoll,而Nginx需要解决高并发压力问题是需要用到epoll,所以我们需要有这样的版本要求。
查看内核版本
- uname -a`命令来查询linux的内核版本。
确认停用selinux
selinux(security-enhanced linux),美国安全局对于强制访问控制的实现,在linux2.6内核以后的版本中,selinux已经成功内核中的一部分。可以说selinux是linux史上最杰出的新安全子系统之一。虽然有了selinux,我们的系统会更安全,但是对于我们的学习Nginx的历程中,会多很多设置,所以这块建议大家将selinux进行关闭。
vim /etc/selinux/config
安装
通过源码安装
需要准备
一键安装下述需要的内容(使用时看这条,下面的不用看也行)
yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-develGCC编译器
Nginx是使用C语言编写的程序,因此想要运行Nginx就需要安装一个编译工具。GCC就是一个开源的编译器集合,用于处理各种各样的语言,其中就包含了C语言。
# 安装
yum install -y gcc
# 检测是否安装完成
gcc --versionPCRE
Nginx在编译过程中需要使用到PCRE库(perl Compatible Regular Expressoin 兼容正则表达式库),因为在Nginx的Rewrite模块和http核心模块都会使用到PCRE正则表达式语法。
# 安装
yum install -y pcre pcre-devel
# 检测是否安装完成
rpm -qa pcre pcre-develzlib
zlib库提供了开发人员的压缩算法,在Nginx的各个模块中需要使用gzip压缩,所以我们也需要提前安装其库及源代码zlib和zlib-devel
# 安装
yum install -y zlib zlib-devel
# 检测是否安装完成
rpm -qa zlib zlib-develOpenSSL
OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包进行安全通信,并且避免被窃听。 SSL:Secure Sockets Layer安全套接协议的缩写,可以在Internet上提供秘密性传输,其目标是保证两个应用间通信的保密性和可靠性。在Nginx中,如果服务器需要提供安全网页时就需要用到OpenSSL库,所以我们需要对OpenSSL的库文件及它的开发安装包进行一个安装。
# 安装
yum install -y openssl openssl-devel
# 检测是否安装完成
rpm -qa openssl openssl-devel下载源码
右键复制链接可以拿到需要下载的版本的链接地址
# 默认下载在当前目录,所以先建好目录结构
wget http://nginx.org/download/nginx-1.16.1.tar.gz解压
tar -xzf nginx-1.16.1.tar.gz
# 执行完上述命令后需要cd进入到解压好的目录查看可以配置的东西
./configure --help
配置需要的包(也可以不配置,之后需要的时候加,详见升级nginx)
工作中用到的
./configure --prefix=/usr/local/nginx --with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module
执行完后,这里的error不是报错哦,是指nginx错误日志的目录
Nginx的源码复杂安装
这种方式和简单的安装配置不同的地方在第一步,通过./configure来对编译参数进行设置,需要我们手动来指定。那么都有哪些参数可以进行设置,接下来我们进行一个详细的说明。
PATH:是和路径相关的配置信息 with:是启动模块,默认是关闭的 without:是关闭模块,默认是开启的
我们先来认识一些简单的路径配置已经通过这些配置来完成一个简单的编译: --prefix=PATH
指向Nginx的安装目录,默认值为/usr/local/nginx--sbin-path=PATH
指向(执行)程序文件(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锁文件的存放路径,默认值为<prefix>/logs/nginx.lock要想使用可以通过如下命令
./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在使用上述命令之前,需要将之前服务器已经安装的nginx进行卸载,卸载的步骤分为三步骤: 步骤一:需要将nginx的进程关闭
./nginx -s stop步骤二:将安装的nginx进行删除
rm -rf /usr/local/nginx步骤三:将安装包之前编译的环境清除掉
make clean正式安装
# 一次性执行(执行这条就不用执行下面的了)
./configure && make && make install
# 分步执行
# 执行配置
./configure
# 编译
make
# 安装
make install通过yum安装
tips:使用源码进行简单安装,我们会发现安装的过程比较繁琐,需要提前准备GCC编译器、PCRE兼容正则表达式库、zlib压缩库、OpenSSL安全通信的软件库包,然后才能进行Nginx的安装。
安装yum-utils
sudo yum install -y yum-utils添加yum源文件
vim /etc/yum.repos.d/nginx.repo
# 上述的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进行安装
yun install -y nginx查看是否安装成功
yum list | grep nginx查看nginx的安装位置
whereis nginx
# 找带sbin的那个或者/usr/local/nginx查看nginx版本
# 进入到nginx安装目录,默认目录是/usr/local/nginx
./nginx -V
解压后的目录解释

- auto:存放的是编译相关的脚本
- CHANGES:版本变更记录
- CHANGES.ru:俄罗斯文的版本变更记录
- conf:nginx默认的配置文件
- configure:nginx软件的自动脚本程序,是一个比较重要的文件,作用如下:
- (1)检测环境及根据环境检测结果生成C代码
- (2)生成编译代码需要的Makefile文件
- contrib:存放的是几个特殊的脚本文件,其中README中对脚本有着详细的说明
- html:存放的是Nginx自带的两个html页面,访问Nginx的首页和错误页面
- LICENSE:许可证的相关描述文件
- man:nginx的man手册
- README:Nginx的阅读指南
- src:Nginx的源代码
Nginx配置成系统服务
# 创建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# 解释
[Unit] 部分:
Description:描述了该服务的简要说明,即 "nginx web service",表示这是一个用于提供 Nginx Web 服务的服务单元。
Documentation:指定了关于该服务的文档链接,这里指向了 Nginx 官方文档的网址。
After:指定了该服务应该在哪个目标(target)之后启动,这里是 network.target,即在网络服务启动后再启动该服务。
[Service] 部分:
Type:指定了服务的类型,这里设置为 forking,表示该服务是一个启动时会派生子进程的守护进程。
PIDFile:指定了保存进程ID(PID)的文件路径,nginx 进程的PID将被写入 /usr/local/nginx/logs/nginx.pid 文件。
ExecStartPre:在服务主进程启动之前执行的命令。该命令会先运行 /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf,用于检查 Nginx 配置文件的语法是否正确。
ExecStart:启动服务的命令,运行 /usr/local/nginx/sbin/nginx 来启动 Nginx 主进程。
ExecReload:重新加载服务的命令,运行 /usr/local/nginx/sbin/nginx -s reload 来重新加载 Nginx 配置。
ExecStop:停止服务的命令,运行 /usr/local/nginx/sbin/nginx -s stop 来停止 Nginx 进程。
PrivateTmp:设置为 true,表示为服务创建私有的临时文件系统。
[Install] 部分:
WantedBy:指定了服务应该被哪个目标(target)所启用,默认是 default.target。
该服务单元文件描述了一个 Nginx Web 服务的启动、停止和重新加载操作,以及相关的配置参数。您可以使用 Systemd 命令来启动、停止、重新加载和管理该服务。使用系统命令来操作Nginx服务(需要完成上面的操作)
# 启动
systemctl start nginx
# 停止
systemctl stop nginx
# 重启
systemctl restart nginx
# 重新加载配置文件
systemctl reload nginx
# 查看nginx状态
systemctl status nginx
# 开机启动
systemctl enable nginxNginx命令配置到系统环境
# 编辑环境变量
vim /etc/profile
# 新增如下语句后保存并退出
export PATH=$PATH:/usr/local/nginx/sbin
# 使其生效
source /etc/profile
# 尝试执行
nginx -Vnginx升级和新增模块
需求
Nginx的版本最开始使用的是Nginx-1.14.2,由于服务升级,需要将Nginx的版本升级到Nginx-1.16.1,要求Nginx不能中断提供服务。
环境准备
# 自行解压安装低版本
./configure
make && make install
# 解压高版本的nginx并进行参数配置和编译(configure并make),不需要进行安装
./configure
make
# 如果需要配置其他东西,请单独使用(./configure 配置项),在make后可以在目录中找到objs(看下图)
升级nginx
方案一:使用Nginx服务信号完成Nginx的升级
# 将老板本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold
# 将高版本的nginx安装目录编译后的objs目录下的nginx文件,拷贝到原来`/usr/local/nginx/sbin`目录下(就是现在安装的低版本的nginx目录)
cd ~/nginx/core/nginx-1.16.1/objs
cp nginx /usr/local/nginx/sbin
# 发送信号USR2给Nginx的1.14.2版本对应的master进程
kill -USR2 PID / kill -USR2 `cat /usr/local/nginx/logs/nginx.pid.oldbin`
# 发送信号QUIT给Nginx的1.14.2版本对应的master进程
kill -QUIT `more /usr/local/logs/nginx.pid.oldbin`方案二:使用Nginx安装目录的make命令完成升级
# 将老板本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold
# 将高版本的nginx安装目录编译后的objs目录下的nginx文件,拷贝到原来`/usr/local/nginx/sbin`目录下(就是现在安装的低版本的nginx目录)
cd ~/nginx/core/nginx-1.16.1/objs
cp nginx /usr/local/nginx/sbin
# 进入到安装目录,执行make upgrade(看下图)
make upgrade
# 查看是否更新成功
./nginx -v
添加模块到Nginx的实现步骤
# 查询当前Nginx的配置参数
nginx -V
# 将nginx安装目录下sbin目录中的nginx二进制文件进行更名
cd /usr/local/nginx/sbin
mv nginx nginxold
# 进入Nginx的安装目录
cd /root/nginx/core/nginx-1.16.1
# 执行make clean清空之前编译的内容
make clean
# 使用configure来配置参数
./configure --with-http_gzip_static_module
# 使用make命令进行编译
make
# 将objs目录下的nginx二进制执行文件移动到nginx安装目录下的sbin目录中
mv objs/nginx /usr/local/nginx/sbin
# 执行更新命令
make upgradeNginx核心配置文件结构
配置文件结构
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;
}
}
}指令名 指令值; #全局块,主要设置Nginx服务器整体运行的配置指令
#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对Nginx服务器的性能影响较大
events {
指令名 指令值;
}
#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、第三方模块配置...
http {
指令名 指令值;
server { #server块,是Nginx配置和虚拟主机相关的内容
指令名 指令值;
location / {
#location块,基于Nginx服务器接收请求字符串与location后面的值进行匹配,对特定请求进行处理
指令名 指令值;
}
}
...
}全局块
user指令
该属性也可以在编译的时候指定,语法如下./configure --user=user --group=group,如果两个地方都进行了设置,最终生效的是配置文件中的配置。 (1)user:用于配置运行Nginx服务器的worker进程的用户和用户组。
| 语法 | user user [group] |
|---|---|
| 默认值 | nobody |
| 位置 | 全局块 |
使用步骤

# 在nginx配置文件中第一行设置一个用户信息"www"
user www;
# 因为没有www这个用户(看上图)
# 创建一个用户
useradd www
# 修改user属性
user www
# 创建`/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>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
<p><em>I am WWW</em></p>
</body>
</html>
# 修改nginx.conf
location / {
root /root/html;
index index.html index.htm;
}
# 测试启动访问
# 页面会报403拒绝访问的错误,因为当前用户没有访问/root/html目录的权限
# 将文件创建到 `/home/www/html/index.html`,修改配置
location / {
root /home/www/html;
index index.html index.htm;
}
# 再次测试启动访问,能正常访问work process指令
worker_processes:用于配置Nginx生成工作进程的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。
master_process:用来指定是否开启工作进程。
| 语法 | master_process on|off; |
|---|---|
| 默认值 | master_process on; |
| 位置 | 全局块 |
| worker_processes:用于配置Nginx生成工作进程的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。 |
| 语法 | worker_processes num/auto; |
|---|---|
| 默认值 | 1 |
| 位置 | 全局块 |
| 如果将worker_processes设置成2,则会看到如下内容: | |
![]() |
其他指令
- daemon:设定Nginx是否以守护进程的方式启动。
| 语法 | daemon on|off; |
|---|---|
| 默认值 | daemon on; |
| 位置 | 全局块 |
- pid:用来配置Nginx当前master进程的进程号ID存储的文件路径。
| 语法 | pid file; |
|---|---|
| 默认值 | 默认为:/usr/local/nginx/logs/nginx.pid |
| 位置 | 全局块 |
- error_log:用来配置Nginx的错误日志存放路径
| 语法 | error_log file [日志级别]; |
|---|---|
| 默认值 | error_log logs/error.log error; |
| 位置 | 全局块、http、server、location |
- include:用来引入其他配置文件,使Nginx的配置更加灵活
| 语法 | include file; |
|---|---|
| 默认值 | 无 |
| 位置 | any |
events块
- accept_mutex:用来设置Nginx网络连接序列化
| 语法 | accept_mutex on|off; |
|---|---|
| 默认值 | accept_mutex on; |
| 位置 | events |
- multi_accept:用来设置是否允许同时接收多个网络连接
| 语法 | multi_accept on|off; |
|---|---|
| 默认值 | multi_accept off; |
| 位置 | events |
- worker_connections:用来配置单个worker进程最大的连接数
| 语法 | worker_connections number; |
|---|---|
| 默认值 | worker_commections 512; |
| 位置 | events |
- use:用来设置Nginx服务器选择哪种事件驱动来处理网络消息。
| 语法 | use method; |
|---|---|
| 默认值 | 根据操作系统定 |
| 位置 | events |
- events指令配置实例 打开Nginx的配置文件 nginx.conf,添加如下配置
events{
accept_mutex on;
multi_accept on;
worker_commections 1024;
use epoll;
}启动测试
./nginx -t
./nginx -s reloadhttp块
定义MIME-Type
我们都知道浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME Type。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型。
# 在Nginx的配置文件中,默认有两行配置
include mime.types;
default_type application/octet-stream;(1)default_type:用来配置Nginx响应前端请求默认的MIME类型。
| 语法 | default_type mime-type; |
|---|---|
| 默认值 | default_type text/plain; |
| 位置 | http、server、location |
在default_type之前还有一句include mime.types,include之前我们已经介绍过,相当于把mime.types文件中MIMT类型与相关类型文件的文件后缀名的对应关系加入到当前的配置文件中。 |
举例来说明: 有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响应性能非常快。
如何实现:
location /get_text {
#这里也可以设置成text/plain
default_type text/html;
return 200 "This is nginx's text";
}
location /get_json{
default_type application/json;
return 200 '{"name":"TOM","age":18}';
}自定义服务日志
Nginx中日志的类型分access.log、error.log。 access.log:用来记录用户所有的访问请求。 error.log:记录nginx本身运行时的错误信息,不会记录用户的访问请求。 Nginx服务器支持对服务日志的格式、大小、输出等进行设置,需要使用到两个指令,分别是access_log和log_format指令。 (1)access_log:用来设置用户访问日志的相关属性。
| 语法 | access_log path[format[buffer=size]] |
|---|---|
| 默认值 | access_log logs/access.log combined; |
| 位置 | http, server, location |
| (2)log_format:用来指定日志的输出格式。 |
| 语法 | log_format name [escape=default|json|none] string....; |
|---|---|
| 默认值 | log_format combined "..."; |
| 位置 | http |
其他配置指令
(1)sendfile:用来设置Nginx服务器是否使用sendfile()传输文件,该属性可以大大提高Nginx处理静态资源的性能
| 语法 | sendfile on|off; |
|---|---|
| 默认值 | sendfile off; |
| 位置 | http、server、location |
| (2)keepalive_timeout:用来设置长连接的超时时间。 |
》为什么要使用keepalive?
我们都知道HTTP是一种无状态协议,客户端向服务端发送一个TCP请求,服务端响应完毕后断开连接。
如何客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。| 语法 | keepalive_timeout time; |
|---|---|
| 默认值 | keepalive_timeout 75s; |
| 位置 | http、server、location |
| (3)keepalive_requests:用来设置一个keep-alive连接使用的次数。 |
| 语法 | keepalive_requests number; |
|---|---|
| 默认值 | keepalive_requests 100; |
| 位置 | http、server、location |
server块和location块
server块和location块都是我们要重点讲解和学习的内容,因为我们后面会对Nginx的功能进行详细讲解,所以这块内容就放到静态资源部署的地方给大家详细说明。
本节我们主要来认识下Nginx默认给的nginx.conf中的相关内容,以及server块与location块在使用的时候需要注意的一些内容。
详见下方的:Nginx静态资源的配置指令
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 404 /50x.html;
location = /50x.html {
root html;
}
}实战——Nginx服务器基础配置实例
前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述。通过这些指令的合理配置,我们就可以让一台Nginx服务器正常工作,并且提供基本的web服务器功能。
接下来我们将通过一个比较完整和最简单的基础配置实例,来巩固下前面所学习的指令及其配置。
需求如下
(1)有如下访问:
http://192.168.200.133:8081/server1/location1
访问的是:index_sr1_location1.html
http://192.168.200.133:8081/server1/location2
访问的是:index_sr1_location2.html
http://192.168.200.133:8082/server2/location1
访问的是:index_sr2_location1.html
http://192.168.200.133:8082/server2/location2
访问的是:index_sr2_location2.html
(2)如果访问的资源不存在,
返回自定义的404页面
(3)将/server1和/server2的配置使用不同的配置文件分割
将文件放到/home/www/conf.d目录下,然后使用include进行合并
(4)为/server1和/server2各自创建一个访问日志文件准备相关文件,目录如下: 
配置的内容如下
##全局块 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块 结束##
}
##http块 end##server1.conf
server{
#配置监听端口和主机名称
listen 8081;
server_name localhost;
#配置请求处理日志存放路径
access_log /home/www/myweb/server1/logs/access.log server1;
#配置错误页面
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server1/location1{
root /home/www/myweb;
index index_sr1_location1.html;
}
#配置处理/server1/location2请求的location
location /server1/location2{
root /home/www/myweb;
index index_sr1_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}server2.conf
server{
#配置监听端口和主机名称
listen 8082;
server_name localhost;
#配置请求处理日志存放路径
access_log /home/www/myweb/server2/logs/access.log server2;
#配置错误页面,对404.html做了定向配置
error_page 404 /404.html;
#配置处理/server1/location1请求的location
location /server2/location1{
root /home/www/myweb;
index index_sr2_location1.html;
}
#配置处理/server2/location2请求的location
location /server2/location2{
root /home/www/myweb;
index index_sr2_location2.html;
}
#配置错误页面转向
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}测试访问 
Nginx静态资源的配置指令
如何查找指令配置
https://nginx.org/en/docs/例如查找listen指令 


listen指令
| 语法 | listen address[:port] [default_server]...; listen port [default_server]...; |
|---|---|
| 默认值 | listen *:80 | *:8000 |
| 位置 | server |
listen 127.0.0.1:8000; // listen localhost:8000 监听指定的IP和端口
listen 127.0.0.1; 监听指定IP的所有端口
listen 8000; 监听指定端口上的连接
listen *:8000; 监听指定端口上的连接default_server
# default_server属性是标识符,用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的address:port,则会默认执行的。如果不指定默认使用的是第一个server。
server{
listen 8080;
server_name 127.0.0.1;
location /{
root html;
index index.html;
}
}
server{
listen 8080 default_server;
server_name localhost;
default_type text/plain;
return 444 'This is a error request';
}server_name指令
用来设置虚拟主机服务名称。
#例如
127.0.0.1 、 localhost 、域名[[www.baidu.com](www.baidu.com) | [www.jd.com](www.jd.com)]| 语法 | server_name name ...; name可以提供多个中间用空格分隔 |
|---|---|
| 默认值 | server_name ""; |
| 位置 | server |
精确匹配
server {
listen 80;
server_name www.itcast.cn 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_name中可以使用正则表达式,并且使用~作为正则表达式字符串的开始标记。
| 代码 | 说明 |
|---|---|
| ^ | 匹配搜索字符串开始位置 |
| $ | 匹配搜索字符串结束位置 |
| . | 匹配除换行符\n之外的任何单个字符 |
| |转义字符,将下一个字符标记为特殊字符 | |
| [xyz] | 字符集,与任意一个指定字符匹配 |
| [a-z] | 字符范围,匹配指定范围内的任何字符 |
| \w | 与以下任意字符匹配 A-Z a-z 0-9 和下划线,等效于[A-Za-z0-9_] |
| \d | 数字字符匹配,等效于[0-9] |
| {n} | 正好匹配n次 |
| {n,} | 至少匹配n次 |
| {n,m} | 匹配至少n次至多m次 |
| * | 零次或多次,等效于{0,} |
| + | 一次或多次,等效于{1,} |
| ? | 零次或一次,等效于{0,1} |
server{
listen 80;
server_name ~^www\.(\w+)\.com$;
default_type text/plain;
return 200 $1 $2 ..;
}
注意 ~后面不能加空格,括号可以取值匹配执行顺序
No1:准确匹配server_name
No2:通配符在开始时匹配server_name成功
No3:通配符在结束时匹配server_name成功
No4:正则表达式匹配server_name成功
No5:被默认的default_server处理,如果没有指定默认找第一个serverlocation指令
# location:用来设置请求的URI
server{
listen 80;
server_name localhost;
location / {
}
location /abc{
}
...
}| 语法 | location [ = | ~ | ~* | ^~ |@ ] uri |
|---|---|
| 默认值 | — |
| 位置 | server,location |
| uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包含正则表达式进行匹配,找到一个匹配度最高的一个,然后在通过包含正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚才匹配度最高的那个location来处理请求。 |
不带符号
要求必须以指定模式开始
server {
listen 80;
server_name 127.0.0.1;
location /abc{
default_type text/plain;
return 200 "access success";
}
}
以下访问都是正确的
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
http://192.168.200.133/abc/
http://192.168.200.133/abcdef=
用于不包含正则表达式的uri前,必须与指定的模式精确匹配
server {
listen 80;
server_name 127.0.0.1;
location =/abc{
default_type text/plain;
return 200 "access success";
}
}
可以匹配到
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
匹配不到
http://192.168.200.133/abc/
http://192.168.200.133/abcdef~
用于表示当前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前,功能和不加符号的一致,唯一不同的是,如果模式匹配,那么就停止搜索其他模式了。
server {
listen 80;
server_name 127.0.0.1;
location ^~/abc{
default_type text/plain;
return 200 "access success";
}
}设置请求资源的目录
root
设置请求的根目录
| 语法 | root path; |
|---|---|
| 默认值 | root html; |
| 位置 | http、server、location |
| path为Nginx服务器接收到请求以后查找资源的根目录路径。 |
alias
用来更改location的URI
| 语法 | alias path; |
|---|---|
| 默认值 | — |
| 位置 | location |
| path为修改后的根路径。 |
区别
# 在`/usr/local/nginx/html`目录下创建一个 images目录,并在目录下放入一张图片`mv.png`图片
location /images {
root /usr/local/nginx/html;
}
# 访问图片的路径为
http://192.168.111.128/images/mv.png
# 如果把root改为alias
location /images {
alias /usr/local/nginx/html;
}
#再次访问上述地址,页面会出现404的错误,查看错误日志会发现是因为地址不对,所以验证了
# root的处理结果是: root路径+location路径
# /usr/local/nginx/html/images/mv.png
# alias的处理结果是:使用alias路径替换location路径
# /usr/local/nginx/html/images
# 需要在alias后面路径改为
location /images {
alias /usr/local/nginx/html/images;
}
# 如果location路径是以/结尾,则alias也必须是以/结尾,root没有要求
location /images/ {
alias /usr/local/nginx/html/images;
}
# 访问就会出问题,查看错误日志还是路径不对,所以需要把alias后面加上 /小结
root的处理结果是: root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的含义。
如果location路径是以/结尾,则alias也必须是以/结尾,root没有要求index指令
设置网站的默认首页
| 语法 | index file ...; |
|---|---|
| 默认值 | index index.html; |
| 位置 | http、server、location |
| index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找,找到第一个为止。 |
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
# 访问该location的时候,可以通过 http://ip:port/,地址后面如果不添加任何内容,则默认依次访问index.html和index.htm,找到第一个来进行返回error_page指令
设置网站的错误页面
| 语法 | error_page code ... [=[response]] uri; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location...... |
指定具体跳转的地址
server {
error_page 404 http://www.itcast.cn;
}可以指定重定向地址
server{
error_page 404 /50x.html;
error_page 500 502 503 504 /50x.html;
location =/50x.html{
root html;
}
}使用location的@符合完成错误信息展示
server{
error_page 404 @jump_to_error;
location @jump_to_error {
default_type text/plain;
return 404 'Not Found Page...';
}
}可选项=[response]的作用是用来将相应代码更改为另外一个
server{
error_page 404 =200 /50x.html;
location =/50x.html{
root html;
}
}
# 这样的话,当返回404找不到对应的资源的时候,在浏览器上可以看到,最终返回的状态码是200,这块需要注意下,编写error_page后面的内容,404后面需要加空格,200前面不能加空格静态资源优化配置语法
sendfile on;
tcp_nopush on;
tcp_nodeplay on;sendfile
用来开启高效的文件传输模式。
| 语法 | sendfile on |off; |
|---|---|
| 默认值 | sendfile off; |
| 位置 | http、server、location... |
请求静态资源的过程
客户端通过网络接口向服务端发送请求,操作系统将这些客户端的请求传递给服务器端应用程序,服务器端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html;
}
}
#在html目录下有一个welcome.html页面,访问地址
http://192.168.111.128/welcome.html处理流程



tcp_nopush
该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输'效率'
| 语法 | tcp_nopush on|off; |
|---|---|
| 默认值 | tcp_nopush off; |
| 位置 | http、server、location |
![]() |
tcp_nodelay
该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的'实时性'
| 语法 | tcp_nodelay on|off; |
|---|---|
| 默认值 | tcp_nodelay on; |
| 位置 | http、server、location |
![]() |
关于tcp_nopush和tcp_nodelay的说明
经过刚才的分析,"tcp_nopush"和”tcp_nodelay“看起来是"互斥的",那么为什么要将这两个值都打开,这个大家需要知道的是在linux2.5.9以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前数据包已经充分“填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数, 然后,tcp_nodelay强制套接字发送数据。由此可知,TCP_NOPUSH可以与TCP_NODELAY一起设置,它比单独配置TCP_NODELAY具有更强的性能。所以我们可以使用如下配置来优化Nginx静态资源的处理实战——Nginx静态资源压缩
在Nginx的配置文件中可以通过配置gzip来对静态资源进行压缩,相关的指令可以配置在http块、server块和location块中
# Nginx可以通过对这些指令进行解析和处理。
ngx_http_gzip_module模块
ngx_http_gzip_static_module模块
ngx_http_gunzip_module模块Gzip模块配置指令
gzip指令
该指令用于开启或者关闭gzip功能
| 语法 | gzip on|off; |
|---|---|
| 默认值 | gzip off; |
| 位置 | http、server、location... |
| 注意只有该指令为打开状态,下面的指令才有效果 |
http{
gzip on;
}gzip_types指令
该指令可以根据响应页的MIME类型选择性地开启Gzip压缩功能
| 语法 | gzip_types mime-type ...; |
|---|---|
| 默认值 | gzip_types text/html; |
| 位置 | http、server、location |
# 所选择的值可以从mime.types文件中进行查找,也可以使用*代表所有。
http{
gzip_types application/javascript;
}gzip_comp_level指令
该指令用于设置Gzip压缩程度,级别从1-9,1表示要是程度最低,要是效率最高,9刚好相反,压缩程度最高,但是效率最低最费时间
| 语法 | gzip_comp_level level; |
|---|---|
| 默认值 | gzip_comp_level 1; |
| 位置 | http、server、location |
http{
gzip_comp_level 6;
}gzip_vary指令
该指令用于设置使用Gzip进行压缩发送是否携带“Vary:Accept-Encoding”头域的响应头部。主要是告诉接收方,所发送的数据经过了Gzip压缩处理
| 语法 | gzip_vary on|off; |
|---|---|
| 默认值 | gzip_vary off; |
| 位置 | http、server、location |
打开时
关闭时
gzip_buffers指令
该指令用于处理请求压缩的缓冲区数量和大小。
| 语法 | gzip_buffers number size; |
|---|---|
| 默认值 | gzip_buffers 32 4k|16 8k; |
| 位置 | http、server、location |
# 其中number:指定Nginx服务器向系统申请缓存空间个数,size指的是每个缓存空间的大小。主要实现的是申请number个每个大小为size的内存空间。这个值的设定一般会和服务器的操作系统有关,所以建议此项不设置,使用默认值即可。
gzip_buffers 4 16K; #缓存空间大小gzip_disable指令
针对不同种类客户端发起的请求,可以选择性地开启和关闭Gzip功能。
| 语法 | gzip_disable regex ...; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location |
| regex:根据客户端的浏览器标志(user-agent)来设置,支持使用正则表达式。指定的浏览器标志不使用Gzip.该指令一般是用来排除一些明显不支持Gzip的浏览器。 |
gzip_disable "MSIE [1-6]\.";gzip_http_version指令
针对不同的HTTP协议版本,可以选择性地开启和关闭Gzip功能。 该指令是指定使用Gzip的HTTP最低版本,该指令一般采用默认值即可。
| 语法 | gzip_http_version 1.0|1.1; |
|---|---|
| 默认值 | gzip_http_version 1.1; |
| 位置 | http、server、location |
gzip_min_length指令
该指令针对传输数据的大小,可以选择性地开启和关闭Gzip功能
| 语法 | gzip_min_length length; |
|---|---|
| 默认值 | gzip_min_length 20; |
| 位置 | http、server、location |
nignx计量大小的单位:bytes[字节] / kb[千字节] / M[兆]
例如: 1024 / 10k|K / 10m|M
Gzip压缩功能对大数据的压缩效果明显,但是如果要压缩的数据比较小的化,可能出现越压缩数据量越大的情况,因此我们需要根据响应内容的大小来决定是否使用Gzip功能,响应页面的大小可以通过头信息中的`Content-Length`来获取。但是如何使用了Chunk编码动态压缩,该指令将被忽略。建议设置为1K或以上。gzip_proxied指令
该指令设置是否对服务端返回的结果进行Gzip压缩
| 语法 | gzip_proxied off|expired|no-cache| no-store|private|no_last_modified|no_etag|auth|any; |
|---|---|
| 默认值 | gzip_proxied off; |
| 位置 | http、server、location |
- 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 - 无条件启用压缩
Gzip和sendfile共存问题
前面在讲解sendfile的时候,提到过,开启sendfile以后,在读取磁盘上的静态资源文件的时候,可以减少拷贝的次数,可以不经过用户进程将静态文件通过网络设备发送出去,但是Gzip要想对资源压缩,是需要经过用户进程进行操作的。所以如何解决两个设置的共存问题。
可以使用ngx_http_gzip_static_module模块的gzip_static指令来解决。
gzip_static指令
检查与访问资源同名的.gz文件时,response中以gzip相关的header返回.gz文件的内容。
| 语法 | gzip_static on | off | always; |
|---|---|
| 默认值 | gzip_static off; |
| 位置 | http、server、location |
添加上述命令后,会报一个错误,unknown directive "gzip_static"主要的原因是Nginx默认是没有添加ngx_http_gzip_static_module模块 |
添加模块到Nginx的实现步骤
# 查询当前Nginx的配置参数
nginx -V
# 将nginx安装目录下sbin目录中的nginx二进制文件进行更名
cd /usr/local/nginx/sbin
mv nginx nginxold
# 进入Nginx的安装目录
cd /root/nginx/core/nginx-1.16.1
# 执行make clean清空之前编译的内容
make clean
# 使用configure来配置参数
./configure --with-http_gzip_static_module
# 使用make命令进行编译
make
# 将objs目录下的nginx二进制执行文件移动到nginx安装目录下的sbin目录中
mv objs/nginx /usr/local/nginx/sbin
# 执行更新命令
make upgradegzip_static测试使用
直接访问
http://192.168.111.128/jquery.js
使用gzip命令进行压缩
cd /usr/local/nginx/html
gzip jquery.js再次访问http://192.168.111.128/jquery.js
静态资源的缓存处理
什么是缓存
缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。
什么是web缓存
Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页
web缓存的种类
客户端缓存
浏览器缓存
服务端缓存
Nginx / Redis / Memcached等浏览器缓存
是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览.
为什么要用浏览器缓存
成本最低的一种缓存实现 减少网络带宽消耗 降低服务器压力 减少网络延迟,加快页面打开速度
浏览器缓存的执行流程
HTTP协议中和页面缓存相关的字段,我们先来认识下:
| header | 说明 |
|---|---|
| Expires | 缓存过期的日期和时间 |
| Cache-Control | 设置和缓存相关的配置信息 |
| Last-Modified | 请求资源最后修改时间 |
| ETag | 请求变量的实体标签的当前值,比如文件的MD5值 |
![]() |
浏览器缓存相关指令
Nginx需要进行缓存相关设置,就需要用到如下的指令
expires指令
该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应答中的“Expires"和”Cache-Control"
| 语法 | expires [modified] time expires epoch|max|off; |
|---|---|
| 默认值 | expires off; |
| 位置 | http、server、location |
time
可以整数也可以是负数,指定过期时间,如果是负数,Cache-Control则为no-cache,如果为整数或0,则Cache-Control的值为max-age=time;
匹配任意多个字符并且以.(htm或js或css或png)结尾的请求,缓存1000秒
缓存10天
无缓存
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年
缓存10年
off
默认不缓存。
add_header指令
用来添加指定的响应头和响应值。
| 语法 | add_header name value [always]; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location... |
| 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>| 指令 | 说明 |
|---|---|
| must-revalidate | 可缓存但必须再向源服务器进行确认 |
| no-cache | 缓存前必须确认其有效性 |
| no-store | 不缓存请求或响应的任何内容 |
| no-transform | 代理不可更改媒体类型 |
| public | 可向任意方提供响应的缓存 |
| private | 仅向特定用户返回响应 |
| proxy-revalidate | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
| max-age=<秒> | 响应最大Age值 |
| s-maxage=<秒> | 公共缓存服务器响应的最大Age值 |
Nginx的跨域问题解决
同源策略
浏览器的同源策略:是一种约定,是浏览器最核心也是最基本的安全功能,如果浏览器少了同源策略,则浏览器的正常功能可能都会受到影响。
同源: 协议、域名(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
不
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://192.168.200.131/user/1
http://192.168.200.131:8080/user/1
不
http://www.nginx.org:80/user/1
http://www.nginx.org/user/1
满足跨域问题
有两台服务器分别为A,B,如果从服务器A的页面发送异步请求到服务器B获取数据,如果服务器A和服务器B不满足同源策略,则就会出现跨域问题。
跨域问题的案例演示及处理
nginx的html目录下新建一个a.html(还需要一个jquery.js文件哦~)
<html>
<head>
<meta charset="utf-8">
<title>跨域问题演示</title>
<script src="jquery.js"></script>
<script>
$(function(){
$("#btn").click(function(){
$.get('http://192.168.111.128:8080/getUser',function(data){
alert(JSON.stringify(data));
});
});
});
</script>
</head>
<body>
<input type="button" value="获取数据" id="btn"/>
</body>
</html>在nginx.conf配置如下内容
server{
listen 8080;
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;
}
}通过浏览器访问测试 
解决方案
add_header指令
该指令可以用来添加一些头信息
| 语法 | add_header name value... |
|---|---|
| 默认值 | — |
| 位置 | http、server、location |
此处用来解决跨域问题,需要添加两个头信息,一个是Access-Control-Allow-Origin,Access-Control-Allow-Methods |
Access-Control-Allow-Origin
直译过来是允许跨域访问的源地址信息,可以配置多个(多个用逗号分隔),也可以使用*代表所有源
Access-Control-Allow-Methods
直译过来是允许跨域访问的请求方式,值可以为 GET POST PUT DELETE...,可以全部设置,也可以根据需要设置,多个用逗号分隔
具体配置方式
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}';
}或单个配置服务器
结果 
静态资源防盗链
什么是资源盗链
资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别人的限制将别人的内容放到自己页面上最终展示给用户。以此来盗取大网站的空间和流量。简而言之就是用别人的东西成就自己的网站。
将上面准备的a.html中加上两张图片的地址
京东: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
# 就是下面这样加
<img src="https://img14.360buyimg.com/n7/jfs/t1/101062/37/2153/254169/5dcbd410E6d10ba22/4ddbd212be225fcd.jpg"/>
<img src="https://pics7.baidu.com/feed/cf1b9d16fdfaaf516f7e2011a7cda1e8f11f7a1a.jpeg?token=551979a23a0995e5e5279b8fa1a48b34&s=BD385394D2E963072FD48543030030BB"/>发现百度的这张图片无法访问 
Nginx防盗链的实现原理
了解防盗链的原理之前,我们得先学习一个HTTP的头信息Referer,当浏览器向web服务器发送请求的时候,一般都会带上Referer,来告诉浏览器该网页是从哪个页面链接过来的。
后台服务器可以根据获取到的这个Referer信息来判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息。
在本地模拟上述的服务器效果

Nginx防盗链的具体实现
valid_referers指令
| 语法 | valid_referers none|blocked|server_names|string... |
|---|---|
| 默认值 | — |
| 位置 | server、location |
| nginx会通就过查看referer自动和valid_referers后面的内容进行匹配,如果匹配到了就将$invalid_referer变量置0,如果没有匹配到,则将$invalid_referer变量置为1,匹配的过程中不区分大小写。 |
例子
location ~*\.(png|jpg|gif){
valid_referers none blocked www.baidu.com 192.168.200.222 *.example.com example.* www.example.org ~\.google\.;
if ($invalid_referer){
return 403;
}
root /usr/local/nginx/html;
}最后一张图是我自己的jj.png 
图片有很多,该如何批量进行防盗链
针对目录进行防盗链
location /images {
valid_referers none blocked www.baidu.com 192.168.200.222 *.example.com example.* www.example.org ~\.google\.;
if ($invalid_referer){
return 403;
}
root /usr/local/nginx/html;
}修改a.html
修改nginx
结果 ①跨域访问
②直接访问
这样我们可以对一个目录下的所有资源进行翻到了操作。
遇到的问题:Referer的限制比较粗,比如随意加一个Referer,上面的方式是无法进行限制的。那么这个问题改如何解决?
此处我们需要用到Nginx的第三方模块ngx_http_accesskey_module,第三方模块如何实现盗链,如果在Nginx中使用第三方模块的功能,这些我们在后面的Nginx的模块篇再进行详细的讲解。
Rewrite功能配置
介绍
Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是用来实现URL的重写。
注意:Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库。Nginx使用的是ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置。
"地址重写"与"地址转发"
重写和转发的区别:
地址重写浏览器地址会发生变化而地址转发则不变 一次地址重写会产生两次请求而一次地址转发只会产生一次请求 地址重写到的页面必须是一个完整的路径而地址转发则不需要 地址重写因为是两次请求所以request范围内属性不能传递给新页面而地址转发因为是一次请求所以可以传递值 地址转发速度快于地址重写
Rewrite常用全局变量
所有变量查询
https://nginx.org/en/docs/varindex.html

日志配置
# 配置日志格式(main后面的内容)及其名称(main)
log_format main '$remote_addr - $request - $status - $request_uri - $time_local - $http_user_agent';使用日志
在请求成功的日志中使用上述格式 
结果展示

Rewrite规则
set指令
该指令用来设置一个新的变量。
| 语法 | set $variable value; |
|---|---|
| 默认值 | — |
| 位置 | server、location、if |
| variable:变量的名称,该变量名称要用"$"作为变量的第一个字符,且不能与Nginx服务器预设的全局变量同名。 |
value:变量的值,可以是字符串、其他变量或者变量的组合等。
例子
server {
listen 8081;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /server {
set $name TOM;
set $age 18;
default_type text/plane;
return 200 $name=$age;
}
}
if指令
该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置。注意,if后面必须有一个空格
| 语法 | if (condition) |
|---|---|
| 默认值 | — |
| 位置 | server、location |
| condition为判定条件,可以支持以下写法 |
变量名
# 如果变量名对应的值为空或者是0,if都判断为false,其他条件为true。
if ($param){
}
# 例如
location /testif {
default_type text/plane;
set $username '';
if ($username) {
return 200 $username;
}
return 200 'paran us empty';
}
#例如
location /testif {
default_type text/plane;
if ($args) {
return 200 sucess;
}
return 200 error;
}
# 访问http://192.168.111.128:8081/testif?a=1,值为sucess
# 访问http://192.168.111.128:8081/testif?0,值为error使用"="和"!="比较变量和字符串是否相等
# 满足条件为true,不满足为false
if ($request_method = POST){
return 405;
}
# 注意:此处和Java不太一样的地方是字符串不需要添加引号。使用正则表达式对变量进行匹配
# 匹配成功返回true,否则返回false。变量与正则表达式之间使用"~","~*","!~","!~\*"来连接。
# "~"代表匹配正则表达式过程中区分大小写,
if ($http_user_agent ~ Safari){
#$http_user_agent的值中是否包含Safari字符串,如果包含返回true
}
# "~\*"代表匹配正则表达式过程中不区分大小写
if ($http_user_agent ~* safari){
#$http_user_agent的值中是否包含safari字符串,如果包含返回true
}
# "!~"和"!~\*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true
# 注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含"}"或者是";"等字符时,就需要把引号加上。判断请求的文件是否存在使用"-f"和"!-f",
# 当使用"-f"时,如果请求的文件存在返回true,不存在返回false。
if (-f $request_filename){
#判断请求的文件是否存在
}
# 当使用"!f"时,如果请求文件不存在,但该文件所在目录存在返回true,文件和目录都不存在返回false,如果文件存在返回false
if (!-f $request_filename){
#判断请求的文件是否不存在
}
location / {
root html;
default_type text/html;
if (!-f $request_filename) {
#判断请求的文件是否存在
return 200 '<h1>file not found !</h1>';
}
}
判断请求的目录是否存在使用"-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,否则返回falsewindows命令行请求
curl -X POST http://192.168.111.128:8081/testifbreak指令
该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效。
| 语法 | break; |
|---|---|
| 默认值 | — |
| 位置 | server、location、if |
location /{
if ($param){
set $id $1;
break;
limit_rate 10k;
}
}return指令
该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在return后的所有Nginx配置都是无效的。
| 语法 | return code [text]; return code URL; return URL; |
|---|---|
| 默认值 | — |
| 位置 | server、location、if |
| code:为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理 | |
| text:为返回给客户端的响应体内容,支持变量的使用 | |
| URL:为返回给客户端的URL地址 |
rewrite指令
该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。
URL和URI的区别:
URI:统一资源标识符
URL:统一资源定位符| 语法 | rewrite regex replacement [flag]; |
|---|---|
| 默认值 | — |
| 位置 | server、location、if |
| regex:用来匹配URI的正则表达式 | |
| replacement:匹配成功后,用于替换URI中被截取内容的字符串 |
如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端。flag:用来设置rewrite对URI的处理行为,可选值有如下:
- last:
- break
- redirect
- permanent
rewrite_log指令
该指令配置是否开启URL重写日志的输出功能。
| 语法 | rewrite_log on|off; |
|---|---|
| 默认值 | rewrite_log off; |
| 位置 | http、server、location、if |
| 开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总。 |
Rewrite的案例
域名跳转
问题分析
如果我们想访问京东网站,大家都知道我们可以输入www.jd.com,但是同样的我们也可以输入www.360buy.com同样也都能访问到京东网站。这个其实是因为京东刚开始的时候域名就是www.360buy.com,后面由于各种原因把自己的域名换成了www.jd.com, 虽然说域名变量,但是对于以前只记住了www.360buy.com的用户来说,我们如何把这部分用户也迁移到我们新域名的访问上来,针对于这个问题,我们就可以使用Nginx中Rewrite的域名跳转来解决。
步骤
# 准备两个域名 www.360buy.com | www.jd.com
vim /etc/hosts
192.168.200.133 www.360buy.com
192.168.200.133 www.jd.com
# 在/usr/local/nginx/html/hm目录下创建一个访问页面
<html>
<title></title>
<body>
<h1>欢迎来到我们的网站</h1>
</body>
</html>#通过Nginx实现当访问www.访问到系统的首页
server {
listen 80;
server_name www.hm.com;
location /{
root /usr/local/nginx/html/hm;
index index.html;
}
}
# 通过Rewrite完成将www.360buy.com的请求跳转到www.jd.com
server {
listen 80;
server_name www.360buy.com;
rewrite ^/ http://www.jd.com permanent;
}如何在域名跳转的过程中携带请求的URI?
# 修改配置信息
server {
listen 80;
server_name www.itheima.com;
rewrite ^(.*) http://www.hm.com$1 permanent;
}我们除了上述说的www.jd.com 、www.360buy.com其实还有我们也可以通过www.jingdong.com来访问,那么如何通过Rewrite来实现多个域名的跳转?
# 添加域名
vim /etc/hosts
192.168.200.133 www.jingdong.com# 修改配置信息
server{
listen 80;
server_name www.360buy.com www.jingdong.com;
rewrite ^(.*) http://www.jd.com$1 permanent;
}域名镜像
# 上述案例中,将www.360buy.com 和 www.jingdong.com都能跳转到www.jd.com,那么www.jd.com我们就可以把它起名叫主域名,其他两个就是我们所说的镜像域名,当然如果我们不想把整个网站做镜像,只想为其中某一个子目录下的资源做镜像,我们可以在location块中配置rewrite功能,比如:
server {
listen 80;
server_name rewrite.myweb.com;
location ^~ /source1{
rewrite ^/resource1(.*) http://rewrite.myweb.com/web$1 last;
}
location ^~ /source2{
rewrite ^/resource2(.*) http://rewrite.myweb.com/web$1 last;
}
}
访问
重定向 
访问
重定向 
独立域名
一个完整的项目包含多个模块,比如购物网站有商品商品搜索模块、商品详情模块已经购物车模块等,那么我们如何为每一个模块设置独立的域名。
# 需求
# 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;
}目录自动添加"/"
通过一个例子来演示下问题
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html;
}
}
# 要想访问上述资源,很简单,只需要通过http://192.168111.128直接就能访问,地址后面不需要加/,但是如果将上述的配置修改为如下内容
server {
listen 80;
server_name localhost;
location /hm {
root html;
index index.html;
}
}server_name_in_redirect
# 快速创建html页面
echo "<h1>Welcom to heima!!</h1>" > index.html
# 这个时候,要想访问上述资源,按照上述的访问方式,我们可以通过http://192.168.111.128/hm/来访问,但是如果地址后面不加斜杠,页面就会出问题。如果不加斜杠,Nginx服务器内部会自动做一个301的重定向,重定向的地址会有一个指令叫server_name_in_redirect on|off;来决定重定向的地址
# 如果该指令为on
# 重定向的地址为: http://server_name/目录名/;
# 如果该指令为off
# 重定向的地址为: http://原URL中的域名/目录名/;所以就拿刚才的地址来说,http://192.168.200.133/hm如果不加斜杠,那么按照上述规则,如果指令server_name_in_redirect为on,则301重定向地址变为 http://localhost/hm/,如果为off,则301重定向地址变为http://192.168.200.133/hm/。后面这个是正常的,前面地址就有问题。# 注意server_name_in_redirect指令在Nginx的0.8.48版本之前默认都是on,之后改成了off,所以现在我们这个版本不需要考虑这个问题,但是如果是0.8.48以前的版本并且server_name_in_redirect设置为on,我们如何通过rewrite来解决这个问题?
# 解决方案
# 我们可以使用rewrite功能为末尾没有斜杠的URL自动添加一个斜杠
server {
listen 80;
server_name localhost;
server_name_in_redirect on;
location /hm {
if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
}
}合并目录
搜索引擎优化(SEO)是一种利用搜索引擎的搜索规则来提供目的网站的有关搜索引擎内排名的方式。我们在创建自己的站点时,可以通过很多中方式来有效的提供搜索引擎优化的程度。其中有一项就包含URL的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担,但是将所有的文件放在一个目录下又会导致文件资源管理混乱并且访问文件的速度也会随着文件增多而慢下来,这两个问题是相互矛盾的,那么使用rewrite如何解决上述问题?
举例
# 网站中有一个资源文件的访问路径时 /server/11/22/33/44/20.html,也就是说20.html存在于第5级目录下,如果想要访问该资源文件,客户端的URL地址就要写成 `http://www.web.name/server/11/22/33/44/20.html`,
server {
listen 80;
server_name www.web.name;
location /server{
root html;
}
}
# 但是这个是非常不利于SEO搜索引擎优化的,同时客户端也不好记.使用rewrite我们可以进行如下配置:
server {
listen 80;
server_name www.web.name;
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指令支持正则表达式的特性。防盗链
防盗链之前我们已经介绍过了相关的知识,在rewrite中的防盗链和之前将的原理其实都是一样的,只不过通过rewrite可以将防盗链的功能进行完善下,当出现防盗链的情况,我们可以使用rewrite将请求转发到自定义的一张图片和页面,给用户比较好的提示信息。下面我们就通过根据文件类型实现防盗链的一个配置实例:
server{
listen 80;
server_name www.web.com;
locatin ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)${
valid_referers none blocked server_names *.web.com;
if ($invalid_referer){
rewrite ^/ http://www.web.com/images/forbidden.png;
}
}
}根据目录实现防盗链配置:
server{
listen 80;
server_name www.web.com;
location /file/{
root /server/file/;
valid_referers none blocked server_names *.web.com;
if ($invalid_referer){
rewrite ^/ http://www.web.com/images/forbidden.png;
}
}
}正向代理
介绍
关于正向代理和反向代理,我们在前面的章节已经通过一张图给大家详细的介绍过了,简而言之就是正向代理代理的对象是客户端,反向代理代理的是服务端,这是两者之间最大的区别。
Nginx即可以实现正向代理,也可以实现反向代理。 我们先来通过一个小案例演示下Nginx正向代理的简单应用。
需求
启动两台虚拟机(代理端:192.168.111.129),(服务端192.168.111.128)
# 服务端的设置,服务端ip(192.168.111.128)
http {
log_format main 'client send request=>clientIp=$remote_addr serverIp=>$host';
server{
listen 80;
server_name localhost;
access_log logs/access.log main;
location {
root html;
index index.html index.htm;
}
}
}使用客户端访问服务端,打开日志查看结果
# 代理服务器设置,代理端ip(192.168.111.129)
log_format main 'client send request ==> clientIp=$remote_addr serverIp=$host';
server {
listen 82;
access_log logs/access.log main;
resolver 8.8.8.8; # 设置DNS的IP 用来解析proxy_pass中的域名(只有当下面的proxy_pass使用了域名才有效,根据实际情况来使用这条)
location / {
# proxy_pass http://$host$request_uri;
proxy_pass http://192.168.111.128$request_uri;
}
}客户端访问代理
查看代理服务器日志
看到客户端192.168.111.1(浏览器)访问了代理服务器192.168.111.129
查看服务端日志
看到代理服务器192.168.111.129将请求代理到服务器192.168.111.128
反向代理
Nginx反向代理模块的指令是由ngx_http_proxy_module模块进行解析,该模块在安装Nginx的时候已经自己加装到Nginx中了
常用指令
proxy_pass
该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。
| 语法 | proxy_pass URL; |
|---|---|
| 默认值 | — |
| 位置 | location |
URL:为要设置的被代理服务器地址,包含传输协议(http,https://)、主机名称或IP地址加端口号、URI等要素。 |
# 举例
proxy_pass http://www.baidu.com;
location /server {
}
proxy_pass http://192.168.200.146;
http://192.168.200.146/server/index.html
proxy_pass http://192.168.200.146/;
http://192.168.200.146/index.html编写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/index.html
# 这个时候,第一个proxy_pass就变成了http://localhost/server/index.html
# 第二个proxy_pass就变成了http://localhost/index.html效果就不一样了。
# 总结!!!:不加/,则带上location,加上/,则不带上location详细说明是否加"/"
推荐写法2!!!
1.location /api {}` 和 `proxy_pass http://backend_server;
请求:http://example.com/api/foo
转发:http://backend_server/api/foo
解释:location 指定的路径 /api 与请求路径匹配,但 proxy_pass 后没有 /,所以请求路径的 api 部分会保留并传递给后端。
2.location /api/ {}` 和 `proxy_pass http://backend_server/;
请求:http://example.com/api/foo
转发:http://backend_server/foo
解释:location 指定的路径 /api/ 与请求路径匹配,proxy_pass 后带有 /,所以 api 部分会被替换,只保留后面的路径部分
3.location /api/ {}` 和 `proxy_pass http://backend_server;
请求:http://example.com/api/foo
转发:http://backend_server/api/foo
解释:即使 location 指定的路径带有 /,但 proxy_pass 后没有 /,所以请求路径的 api 部分仍会保留并传递给后端
4.location /api {} 和 `proxy_pass http://backend_server/;
请求:http://example.com/api/foo
转发:http://backend_server//foo
解释:这种配置下,proxy_pass 带有 /,但 location 没有 /,会导致路径中出现双斜杠。这种情况通常不推荐。
-----------------------------------正则匹配同上-------------------------------------
5.location ^~ /filePreviewer {} 和 proxy_pass http://127.0.0.1:8012/onlinePreview;
请求:http://example.com/filePreviewer/doc1
转发:http://127.0.0.1:8012/onlinePreview/doc1
解释:这种配置下,proxy_pass 和 location 没有 /,Nginx 会将 `/filePreviewer` 后面的路径保留,并附加到 `proxy_pass` 指定的 URL 之后。
该写法与第二个写法是一样的
6.location ~ ^/api/(.*)$ {} 和 proxy_pass http://backend_server/$1;
请求:http://example.com/api/foo
转发:http://backend_server/foo
解释:在这种配置下,正则表达式 ^/api/(.*)$ 匹配 /api/ 后的任何内容,并捕获到变量 $1。proxy_pass 将被替换为 http://backend_server/ 加上 $1 的值,所以请求路径中的 api 部分被去掉,直接传递剩余的路径部分。
7.location ~ ^/api/(.*)$ {} 和 proxy_pass http://backend_server/$1/;
请求:http://example.com/api/foo
转发:http://backend_server/foo/
解释:在这种配置下,末尾的 / 会被直接添加到被代理的 URL 后。这种配置通常不常见,因为它会在 URL 末尾强制添加一个 /,这可能并不是预期的行为。proxy_set_header
该指令可以更改Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给代理的服务器
| 语法 | proxy_set_header field value; |
|---|---|
| 默认值 | proxy_set_header Host $proxy_host; proxy_set_header Connection close; |
| 位置 | http、server、location |
| 注:如果想要看到结果,必须在被代理的服务器上来获取添加的头信息。 |
# 例子
#被代理服务器(192.168.111.129)
server {
listen 8080;
server_name localhost;
default_type text/plain;
return 200 $http_username;
}
# 代理服务器(192.168.111.128)
server {
listen 8080;
server_name localhost;
location /server {
proxy_pass http://192.168.111.129:8080/;
proxy_set_header username TOM;
}
}proxy_redirect
该指令是用来重置头信息中的"Location"和"Refresh"的值。
| 语法 | proxy_redirect redirect replacement; proxy_redirect default; proxy_redirect off; |
|---|---|
| 默认值 | proxy_redirect default; |
| 位置 | http、server、location |
proxy_redirect redirect replacement;
redirect:目标,Location的值
replacement:要替换的值
proxy_redirect default;
default;
将location块的uri变量作为replacement,
将proxy_pass变量作为redirect进行替换
proxy_redirect off;
关闭proxy_redirect的功能为什么要用该指令?
# 服务端[192.168.111.129]
server {
listen 8081;
server_name localhost;
location / {
if (!-f $request_filename){
return 302 http://192.168.111.129;
}
}
}
# 代理服务端[192.168.111.128]
server {
listen 8081;
server_name localhost;
location / {
proxy_pass http://192.168.111.129:8081/;
# 这里会跳转到http://192.168.111.128(也就是下面的server块)
proxy_redirect http://192.168.111.129 http://192.168.111.128;
#视频中上面这行是加斜杠的,如下:
#proxy_redirect http://192.168.111.129/ http://192.168.111.128/;
}
}
server {
listen 80;
server_name loaclhost;
location / {
# 这里又会代理到服务端
proxy_pass http://192.168.111.129:8081/;
}
}实战——Nginx反向代理
服务器1,2,3存在两种情况
- 第一种情况: 三台服务器的内容不一样。
- 第二种情况: 三台服务器的内容是一样。
# 如果服务器1、服务器2和服务器3的内容不一样,那我们可以根据用户请求来分发到不同的服务器。
#代理服务器
server {
listen 8082;
server_name localhost;
location /server1 {
proxy_pass http://192.168.111.129:9001/;
}
location /server2 {
proxy_pass http://192.168.111.129:9002/;
}
location /server3 {
proxy_pass http://192.168.111.129:9003/;
}
}
#服务端
#server1
server {
listen 9001;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.111.129:9001</h1>'
}
#server2
server {
listen 9002;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.111.129:9002</h1>'
}
#server3
server {
listen 9003;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.111.129:9003</h1>'
}如果服务器1、服务器2和服务器3的内容是一样的,该如何处理?
Nginx的安全控制
安全隔离
通过代理分开了客户端到应用程序服务器端的连接,实现了安全措施。在反向代理之前设置防火墙,仅留一个入口供代理服务器访问。 
使用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的支持,这个我们之前已经准备好了。
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进行升级,这个可以实现不停机添加新模块的功能Nginx的SSL相关指令
ssl
该指令用来在指定的服务器开启HTTPS,可以使用 listen 443 ssl,后面这种方式更通用些。
| 语法 | ssl on | off; |
|---|---|
| 默认值 | ssl off; |
| 位置 | http、server |
server{
listen 443 ssl;
}ssl_certificate
为当前这个虚拟主机指定一个带有PEM格式证书的证书。
| 语法 | ssl_certificate file; |
|---|---|
| 默认值 | — |
| 位置 | http、server |
ssl_certificate_key
该指令用来指定PEM secret key文件的路径
| 语法 | ssl_ceritificate_key file; |
|---|---|
| 默认值 | — |
| 位置 | http、server |
ssl_session_cache
该指令用来配置用于SSL会话的缓存
| 语法 | ssl_sesion_cache off|none|[builtin[:size]] [shared:name:size] |
|---|---|
| 默认值 | ssl_session_cache none; |
| 位置 | http、server |
# 禁用会话缓存,客户端不得重复使用会话
off
# 禁止使用会话缓存,客户端可以重复使用,但是并没有在缓存中存储会话参数
none
# 内置OpenSSL缓存,仅在一个工作进程中使用。
builtin
# 所有工作进程之间共享缓存,缓存的相关信息用name和size来指定
sharedssl_session_timeout
开启SSL会话功能后,设置客户端能够反复使用储存在缓存中的会话参数时间。 5m:5分钟
| 语法 | ssl_session_timeout time; |
|---|---|
| 默认值 | ssl_session_timeout 5m; |
| 位置 | http、server |
ssl_ciphers
指出允许的密码,密码指定为OpenSSL支持的格式 可以使用
openssl ciphers查看openssl支持的格式。
| 语法 | ssl_ciphers ciphers; |
|---|---|
| 默认值 | ssl_ciphers HIGH:!aNULL:!MD5; |
| 位置 | http、server |
ssl_prefer_server_ciphers
该指令指定是否服务器密码优先客户端密码
| 语法 | ssl_perfer_server_ciphers on|off; |
|---|---|
| 默认值 | ssl_perfer_server_ciphers off; |
| 位置 | http、server |
生成证书
方式一
使用阿里云/腾讯云等第三方服务进行购买。
方式二
使用openssl生成证书
# 先要确认当前系统是否有安装openssl
openssl version
# 安装下面的命令进行生成
mkdir /root/cert
cd /root/cert
openssl genrsa -des3 -out server.key 1024
# 做完下面这步如下图所示,这次执行的时候,所设密码均为root
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
# 下面这步做完后可以看到第二张图,此处密码为root
openssl rsa -in server.key.org -out server.key
# 下面这步做完后可以看到第三张图
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt


最后生成的文件
访问基本路径
server {
listen 80;
server_name test.cn;
#charset koi8-r;
location / {
access_log logs/access.log main;
root html;
index index.html index.htm;
# rewrite ^(.*) https://test.cn$1;
}
#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;
}
}
开启SSL实例
# 在windows中配置host===》 192.168.111.128 test.cn
server {
listen 443 ssl;
server_name test.cn;
# 证书文件
ssl_certificate /root/cert/server.crt;
# 证书秘钥
ssl_certificate_key /root/cert/server.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;
}
}
http转发到https
server {
listen 80;
server_name test.cn;
#charset koi8-r;
location / {
access_log logs/access.log main;
# root html;
# index index.html index.htm;
rewrite ^(.*) https://test.cn$1;
}
#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;
}
}

反向代理系统调优
反向代理值Buffer和Cache Buffer翻译过来是"缓冲",Cache翻译过来是"缓存"。
总结
相同点:
两种方式都是用来提供IO吞吐效率,都是用来提升Nginx代理的性能。
不同点:
缓冲主要用来解决不同设备之间数据传递速度不一致导致的性能低的问题,缓冲中的数据一旦此次操作完成后,就可以删除。
缓存主要是备份,将被代理服务器的数据缓存一份到代理服务器,这样的话,客户端再次获取相同数据的时候,就只需要从代理服务器上获取,效率较高,缓存中的数据可以重复使用,只有满足特定条件才会删除.proxy_buffering
该指令用来开启或者关闭代理服务器的缓冲区;
| 语法 | proxy_buffering on|off; |
|---|---|
| 默认值 | proxy_buffering on; |
| 位置 | http、server、location |
proxy_buffers
该指令用来指定单个连接从代理服务器读取响应的缓存区的个数和大小。 number:缓冲区的个数 size:每个缓冲区的大小,缓冲区的总大小就是number*size
| 语法 | proxy_buffers number size; |
|---|---|
| 默认值 | proxy_buffers 8 4k | 8K;(与系统平台有关) |
| 位置 | http、server、location |
proxy_buffer_size
该指令用来设置从被代理服务器获取的第一部分响应数据的大小。保持与proxy_buffers中的size一致即可,当然也可以更小。
| 语法 | proxy_buffer_size size; |
|---|---|
| 默认值 | proxy_buffer_size 4k | 8k;(与系统平台有关) |
| 位置 | http、server、location |
proxy_busy_buffers_size
该指令用来限制同时处于BUSY状态的缓冲总大小。
proxy_temp_path
当缓冲区存满后,仍未被Nginx服务器完全接受,响应数据就会被临时存放在磁盘文件上,该指令设置文件路径 注意path最多设置三层。
| 语法 | proxy_temp_path path; |
|---|---|
| 默认值 | proxy_temp_path proxy_temp; |
| 位置 | http、server、location |
proxy_temp_file_write_size
该指令用来设置磁盘上缓冲文件的大小。
| 语法 | proxy_temp_file_write_size size; |
|---|---|
| 默认值 | proxy_temp_file_write_size 8K|16K; |
| 位置 | http、server、location |
通用网站的配置
# 根据项目的具体内容进行相应的调节。
proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;Nginx负载均衡
负载均衡概述
早期的网站流量和业务功能都比较简单,单台服务器足以满足基本的需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也跟着越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器进行性能的水平扩展及避免单点故障出现。那么如何将不同用户的请求流量分发到不同的服务器上呢? 
负载均衡的原理及处理流程

这里面涉及到两个重要的角色分别是"应用集群"和"负载均衡器"。
应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。
负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。
负载均衡的作用
1、解决服务器的高并发压力,提高应用程序的处理性能。
2、提供故障转移,实现高可用。
3、通过添加或减少服务器数量,增强网站的可扩展性。
4、在负载均衡器上进行过滤,可以提高系统的安全性。
负载均衡常用的处理方式
方式一:用户手动选择
这种方式比较原始,只要实现的方式就是在网站主页上面提供不同线路、不同服务器链接方式,让用户来选择自己访问的具体服务器,来实现负载均衡。
方式二:DNS轮询方式
DNS
域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换。
大多域名注册商都支持对同一个主机名添加多条A记录,这就是DNS轮询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,这样就能完成简单的负载均衡。DNS轮询的成本非常低,在一些不重要的服务器,被经常使用。 
清空本地的dns缓存
ipconfig/flushdns我们发现使用DNS来实现轮询,不需要投入过多的成本,虽然DNS轮询成本低廉,但是DNS负载均衡存在明显的缺点。
1.可靠性低
假设一个域名DNS轮询多台服务器,如果其中的一台服务器发生故障,那么所有的访问该服务器的请求将不会有所回应,即使你将该服务器的IP从DNS中去掉,但是由于各大宽带接入商将众多的DNS存放在缓存中,以节省访问时间,导致DNS不会实时更新。所以DNS轮流上一定程度上解决了负载均衡问题,但是却存在可靠性不高的缺点。
2.负载均衡不均衡
DNS负载均衡采用的是简单的轮询负载算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能好的服务器多分配请求,另外本地计算机也会缓存已经解析的域名到IP地址的映射,这也会导致使用该DNS服务器的用户在一定时间内访问的是同一台Web服务器,从而引发Web服务器减的负载不均衡。
负载不均衡则会导致某几台服务器负荷很低,而另外几台服务器负荷确很高,处理请求的速度慢,配置高的服务器分配到的请求少,而配置低的服务器分配到的请求多。
方式三:四/七层负载均衡
介绍四/七层负载均衡之前,我们先了解一个概念,OSI(open system interconnection),叫开放式系统互联模型,这个是由国际标准化组织ISO指定的一个不基于具体机型、操作系统或公司的网络体系结构。该模型将网络通信的工作分为七层。 
应用层:为应用程序提供网络服务。
表示层:对数据进行格式化、编码、加密、压缩等操作。
会话层:建立、维护、管理会话连接。
传输层:建立、维护、管理端到端的连接,常见的有TCP/UDP。
网络层:IP寻址和路由选择
数据链路层:控制网络层与物理层之间的通信。
物理层:比特流传输。
所谓四层负载均衡指的是OSI七层模型中的传输层,主要是基于IP+PORT的负载均衡
实现四层负载均衡的方式:
硬件:F5 BIG-IP、Radware等
软件:LVS、Nginx、Hayproxy等所谓的七层负载均衡指的是在应用层,主要是基于虚拟的URL或主机IP的负载均衡
实现七层负载均衡的方式:
软件:Nginx、Hayproxy等四层和七层负载均衡的区别
四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则在最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的要高。
四层负载均衡不识别域名,而七层负载均衡识别域名。处理四层和七层负载以为其实还有二层、三层负载均衡,二层是在数据链路层基于mac地址来实现负载均衡,三层是在网络层一般采用虚拟IP地址的方式实现负载均衡。
实际环境采用的模式
四层负载(LVS)+七层负载(Nginx)Nginx七层负载均衡
Nginx要实现七层负载均衡需要用到proxy_pass代理模块配置。Nginx默认安装支持这个模块,我们不需要再做任何处理。Nginx的负载均衡是在Nginx的反向代理基础上把用户的请求根据指定的算法分发到一组【upstream虚拟服务池】。
Nginx七层负载均衡的指令
upstream指令
该指令是用来定义一组服务器,它们可以是监听不同端口的服务器,并且也可以是同时监听TCP和Unix socket的服务器。服务器可以指定不同的权重,默认为1。
| 语法 | upstream name |
|---|---|
| 默认值 | — |
| 位置 | http |
server指令
该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者unix socket
| 语法 | server name [paramerters] |
|---|---|
| 默认值 | — |
| 位置 | upstream |
Nginx七层负载均衡的实现流程
服务端设置
server {
listen 9001;
server_name 192.168.111.128;
default_type text/html;
location / {
return 200 '<h1>192.168.111.128:9001</h1>';
}
}
server {
listen 9002;
server_name 192.168.111.128;
default_type text/html;
location / {
return 200 '<h1>192.168.111.128:9002</h1>';
}
}
server {
listen 9003;
server_name 192.168.111.128;
default_type text/html;
location / {
return 200 '<h1>192.168.111.128:9003</h1>';
}
}负载均衡器设置
upstream backend {
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location / {
proxy_pass http://backend;
}
}负载均衡状态
代理服务器在负责均衡调度中的状态有以下几个:
| 状态 | 概述 |
|---|---|
| down | 当前的server暂时不参与负载均衡 |
| backup | 预留的备份服务器 |
| max_fails | 允许请求失败的次数 |
| fail_timeout | 经过max_fails失败后, 服务暂停时间 |
| max_conns | 限制最大的接收连接数 |
down
将该服务器标记为永久不可用,那么该代理服务器将不参与负载均衡。
upstream backend {
server 192.168.111.128:9001 down;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location / {
proxy_pass http://backend;
}
}该状态一般会对需要停机维护的服务器进行设置。
backup
将该服务器标记为备份服务器,当主服务器不可用时,将用来传递请求。
upstream backend {
server 192.168.111.128:9001 down;
server 192.168.111.128:9002 backup;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location / {
proxy_pass http://backend;
}
}此时需要将9094端口的访问禁止掉来模拟下唯一能对外提供访问的服务宕机以后,backup的备份服务器就要开始对外提供服务,此时为了测试验证,我们需要使用防火墙来进行拦截。
介绍一个工具firewall-cmd,该工具是Linux提供的专门用来操作firewall的。
查询防火墙中指定的端口是否开放
firewall-cmd --query-port=9001/tcp如何开放一个指定的端口
firewall-cmd --permanent --add-port=9002/tcp批量添加开发端口
firewall-cmd --permanent --add-port=9001-9003/tcp如何移除一个指定的端口
firewall-cmd --permanent --remove-port=9003/tcp重新加载
firewall-cmd --reload其中 --permanent表示设置为持久
--add-port表示添加指定端口
--remove-port表示移除指定端口
max_conns
max_conns=number:用来设置代理服务器同时活动链接的最大数量,默认为0,表示不限制,使用该配置可以根据后端服务器处理请求的并发量来进行设置,防止后端服务器被压垮。
max_fails和fail_timeout
max_fails=number:设置允许请求代理服务器失败的次数,默认为1。
fail_timeout=time:设置经过max_fails失败后,服务暂停的时间,默认是10秒。
upstream backend{
server 192.168.111.128:9001 down;
server 192.168.111.128:9002 backup;
server 192.168.111.128:9003 max_fails=3 fail_timeout=15;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}负载均衡策略
介绍完Nginx负载均衡的相关指令后,我们已经能实现将用户的请求分发到不同的服务器上,那么除了采用默认的分配方式以外,我们还能采用什么样的负载算法?
Nginx的upstream支持如下六种方式的分配算法,分别是:
| 算法名称 | 说明 |
|---|---|
| 轮询 | 默认方式 |
| weight | 权重方式 |
| ip_hash | 依据ip分配方式 |
| least_conn | 依据最少连接方式 |
| url_hash | 依据URL分配方式 |
| fair | 依据响应时间方式 |
轮询
是upstream模块负载均衡默认的策略。每个请求会按时间顺序逐个分配到不同的后端服务器。轮询不需要额外的配置。
upstream backend{
server 192.168.111.128:9001 weight=1;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}weight加权[加权轮询]
weight=number:用来设置服务器的权重,默认为1,权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所有此策略比较适合服务器的硬件配置差别比较大的情况。
upstream backend{
server 192.168.111.128:9001 weight=10;
server 192.168.111.128:9002 weight=5;
server 192.168.111.128:9003 weight=3;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}ip_hash
当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个IP的用户在后端Web服务器A上登录后,在访问该站点的其他URL,能保证其访问的还是后端web服务器A。
| 语法 | ip_hash; |
|---|---|
| 默认值 | — |
| 位置 | upstream |
upstream backend{
ip_hash;
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}需要额外多说一点的是使用ip_hash指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接收的请求少,而且设置后端服务器权重等方法将不起作用。

least_conn
最少连接,把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
upstream backend{
least_conn;
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。 
url_hash
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。
upstream backend{
hash &request_uri;
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}访问如下地址:
http://192.168.111.128:8083/a
http://192.168.111.128:8083/b
http://192.168.111.128:8083/c
fair
fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。那么如何使用第三方模块的fair负载均衡策略。
upstream backend{
fair;
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}但是如何直接使用会报错,因为fair属于第三方模块实现的负载均衡。需要添加nginx-upstream-fair,如何添加对应的模块:
# 下载nginx-upstream-fair模块
https://github.com/gnosek/nginx-upstream-fair
# 将下载的文件上传到服务器并进行解压缩
unzip nginx-upstream-fair-master.zip
# 重命名资源
mv nginx-upstream-fair-master fair
# 使用./configure命令将资源添加到Nginx模块中
./configure --add-module=/root/fair
# 编译
make编译可能会出现如下错误,ngx_http_upstream_srv_conf_t结构中缺少default_port 
解决方案: 在Nginx的源码中 src/http/ngx_http_upstream.h,找到ngx_http_upstream_srv_conf_s,在模块中添加添加default_port属性
in_port_t default_port
然后再进行make.
# 更新Nginx
# 将sbin目录下的nginx进行备份
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold
# 将安装目录下的objs中的nginx拷贝到sbin目录
cd objs
cp nginx /usr/local/nginx/sbin
# 更新Nginx
cd ../
make upgrade
# 编译测试使用Nginx上面介绍了Nginx常用的负载均衡的策略,有人说是5种,是把轮询和加权轮询归为一种,也有人说是6种。那么在咱们以后的开发中到底使用哪种,这个需要根据实际项目的应用场景来决定的。
负载均衡案例
案例一:对所有请求实现一般轮询规则的负载均衡
upstream backend{
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}案例二:对所有请求实现加权轮询规则的负载均衡
upstream backend{
server 192.168.111.128:9001 weight=7;
server 192.168.111.128:9002 weight=5;
server 192.168.111.128:9003 weight=3;
}
server {
listen 8083;
server_name 192.168.111.128;
location /{
proxy_pass http://backend;
}
}案例三:对特定资源实现负载均衡
upstream videobackend{
server 192.168.111.128:9001;
server 192.168.111.128:9002;
}
upstream filebackend{
server 192.168.111.128:9003;
server 192.168.111.128:9004;
}
server {
listen 8084;
server_name 192.168.111.128;
location /video/ {
proxy_pass http://videobackend;
}
location /file/ {
proxy_pass http://filebackend;
}
}案例四:对不同域名实现负载均衡
upstream itcastbackend{
server 192.168.111.128:9001;
server 192.168.111.128:9002;
}
upstream itheimabackend{
server 192.168.111.128:9003;
server 192.168.111.128:9004;
}
server {
listen 8085;
server_name 192.168.111.128;
location / {
proxy_pass http://itcastbackend;
}
}
server {
listen 8086;
server_name 192.168.111.128;
location / {
proxy_pass http://itheimabackend;
}
}案例五:实现带有URL重写的负载均衡
upstream backend{
server 192.168.111.128:9001;
server 192.168.111.128:9002;
server 192.168.111.128:9003;
}
server {
listen 80;
server_name 192.168.111.128;
location /file/ {
rewrite ^(/file/.*) /server/$1 last;
}
location /server {
proxy_pass http://backend;
}
}Nginx四层负载均衡
Nginx在1.9之后,增加了一个stream模块,用来实现四层协议的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡。
四层协议负载均衡的实现,一般都会用到LVS、HAProxy、F5等,要么很贵要么配置很麻烦,而Nginx的配置相对来说更简单,更能快速完成工作。
添加stream模块的支持
Nginx默认是没有编译这个模块的,需要使用到stream模块,那么需要在编译的时候加上--with-stream。 完成添加--with-stream的实现步骤:
》将原有/usr/local/nginx/sbin/nginx进行备份
》拷贝nginx之前的配置信息
》在nginx的安装源码进行配置指定对应模块 ./configure --with-stream
》通过make模板进行编译
》将objs下面的nginx移动到/usr/local/nginx/sbin下
》在源码目录下执行 make upgrade进行升级,这个可以实现不停机添加新模块的功能Nginx四层负载均衡的指令
stream指令
该指令提供在其中指定流服务器指令的配置文件上下文。和http指令同级。
| 语法 | stream |
|---|---|
| 默认值 | — |
| 位置 | main |
upstream指令
该指令和http的upstream指令是类似的。
四层负载均衡的案例
需求分析

实现步骤 方法一: (1)准备Redis服务器,在一条服务器上准备三个Redis,端口分别是6379,6378
1.上传redis的安装包,redis-4.0.14.tar.gz 2.将安装包进行解压缩
tar -zxf redis-4.0.14.tar.gz3.进入redis的安装包
cd redis-4.0.144.使用make和install进行编译和安装
make PREFIX=/usr/local/redis/redis01 install5.拷贝redis配置文件redis.conf到/usr/local/redis/redis01/bin目录中
cp redis.conf /usr/local/redis/redis01/bin6.修改redis.conf配置文件
port 6379 #redis的端口
daemonize yes #后台启动redis7.将redis01复制一份为redis02
cd /usr/local/redis
cp -r redis01 redis028.将redis02文件文件夹中的redis.conf进行修改
port 6378 #redis的端口
daemonize yes #后台启动redis9.分别启动,即可获取两个Redis.并查看
ps -ef | grep redis使用Nginx将请求分发到不同的Redis服务器上。
方法2:
docker run --name redis -d -p 6379:6379 redis
docker run --name redis2 -d -p 6378:6379 redis(2)准备Tomcat服务器. 方法1: 1.上传tomcat的安装包,apache-tomcat-8.5.56.tar.gz 2.将安装包进行解压缩
tar -zxf apache-tomcat-8.5.56.tar.gz3.进入tomcat的bin目录
cd apache-tomcat-8.5.56/bin
./startup方法2:
docker run -id --name tomcat -p 8080:8080 tomcatnginx.conf配置
stream {
upstream redisbackend {
server 192.168.111.128:6379;
server 192.168.111.128:6378;
}
upstream tomcatbackend {
server 192.168.111.128:8080;
}
server {
listen 81;
proxy_pass redisbackend;
}
server {
listen 82;
proxy_pass tomcatbackend;
}
}访问测试 
Nginx缓存集成(没学,基本用不到,一般用redis)
缓存的概念
缓存就是数据交换的缓冲区(称作:Cache),当用户要获取数据的时候,会先从缓存中去查询获取数据,如果缓存中有就会直接返回给用户,如果缓存中没有,则会发请求从服务器重新查询数据,将数据返回给用户的同时将数据放入缓存,下次用户就会直接从缓存中获取数据。 
缓存其实在很多场景中都有用到,比如:
| 场景 | 作用 |
|---|---|
| 操作系统磁盘缓存 | 减少磁盘机械操作 |
| 数据库缓存 | 减少文件系统的IO操作 |
| 应用程序缓存 | 减少对数据库的查询 |
| Web服务器缓存 | 减少对应用服务器请求次数 |
| 浏览器缓存 | 减少与后台的交互次数 |
缓存的优点 1.减少数据传输,节省网络流量,加快响应速度,提升用户体验; 2.减轻服务器压力; 3.提供服务端的高可用性; 缓存的缺点 1.数据的不一致 2.增加成本
本次课程注解讲解的是Nginx,Nginx作为web服务器,Nginx作为Web缓存服务器,它介于客户端和应用服务器之间,当用户通过浏览器访问一个URL时,web缓存服务器会去应用服务器获取要展示给用户的内容,将内容缓存到自己的服务器上,当下一次请求到来时,如果访问的是同一个URL,web缓存服务器就会直接将之前缓存的内容返回给客户端,而不是向应用服务器再次发送请求。web缓存降低了应用服务器、数据库的负载,减少了网络延迟,提高了用户访问的响应速度,增强了用户的体验。
Nginx的web缓存服务
Nginx是从0.7.48版开始提供缓存功能。Nginx是基于Proxy Store来实现的,其原理是把URL及相关组合当做Key,在使用MD5算法对Key进行哈希,得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录中。它可以支持任意URL连接,同时也支持404/301/302这样的非200状态码。Nginx即可以支持对指定URL或者状态码设置过期时间,也可以使用purge命令来手动清除指定URL的缓存。

Nginx缓存设置的相关指令
Nginx的web缓存服务主要是使用ngx_http_proxy_module模块相关指令集来完成,接下来我们把常用的指令来进行介绍下。
proxy_cache_path
该指定用于设置缓存文件的存放路径
| 语法 | proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time][max_size=size]; |
|---|---|
| 默认值 | — |
| 位置 | http |
| path:缓存路径地址,如: |
/usr/local/proxy_cachelevels: 指定该缓存空间对应的目录,最多可以设置3层,每层取值为1|2如 :
levels=1:2 缓存空间有两层目录,第一次是1个字母,第二次是2个字母
举例说明:
itheima[key]通过MD5加密以后的值为 43c8233266edce38c2c9af0694e2107d
levels=1:2 最终的存储路径为/usr/local/proxy_cache/d/07
levels=2:1:2 最终的存储路径为/usr/local/proxy_cache/7d/0/21
levels=2:2:2 最终的存储路径为??/usr/local/proxy_cache/7d/10/e2keys_zone:用来为这个缓存区设置名称和指定大小,如:
keys_zone=itcast:200m 缓存区的名称是itcast,大小为200M,1M大概能存储8000个keysinactive:指定缓存的数据多次时间未被访问就将被删除,如:
inactive=1d 缓存数据在1天内没有被访问就会被删除max_size:设置最大缓存空间,如果缓存空间存满,默认会覆盖缓存时间最长的资源,如:
max_size=20g配置实例:
http{
proxy_cache_path /usr/local/proxy_cache keys_zone=itcast:200m levels=1:2:1 inactive=1d max_size=20g;
}
proxy_cache
该指令用来开启或关闭代理缓存,如果是开启则自定使用哪个缓存区来进行缓存。
| 语法 | proxy_cache zone_name|off; |
|---|---|
| 默认值 | proxy_cache off; |
| 位置 | http、server、location |
zone_name:指定使用缓存区的名称
proxy_cache_key
该指令用来设置web缓存的key值,Nginx会根据key值MD5哈希存缓存。
| 语法 | proxy_cache_key key; |
|---|---|
| 默认值 | proxy_cache_key $scheme$proxy_host$request_uri; |
| 位置 | http、server、location |
proxy_cache_valid
该指令用来对不同返回状态码的URL设置不同的缓存时间
| 语法 | proxy_cache_valid [code ...] time; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location |
如:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
为200和302的响应URL设置10分钟缓存,为404的响应URL设置1分钟缓存
proxy_cache_valid any 1m;
对所有响应状态码的URL都设置1分钟缓存proxy_cache_min_uses
该指令用来设置资源被访问多少次后被缓存
| 语法 | proxy_cache_min_uses number; |
|---|---|
| 默认值 | proxy_cache_min_uses 1; |
| 位置 | http、server、location |
proxy_cache_methods
该指令用户设置缓存哪些HTTP方法
| 语法 | proxy_cache_methods GET|HEAD|POST; |
|---|---|
| 默认值 | proxy_cache_methods GET HEAD; |
| 位置 | http、server、location |
默认缓存HTTP的GET和HEAD方法,不缓存POST方法。
Nginx缓存设置案例
需求分析

步骤实现
1.环境准备
应用服务器的环境准备
(1)在192.168.200.146服务器上的tomcat的webapps下面添加一个js目录,并在js目录中添加一个jquery.js文件
(2)启动tomcat
(3)访问测试
http://192.168.200.146:8080/js/jquery.jsNginx的环境准备
(1)完成Nginx反向代理配置
http{
upstream backend{
server 192.168.200.146:8080;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://backend/js/;
}
}
}(2)完成Nginx缓存配置
4.添加缓存配置
http{
proxy_cache_path /usr/local/proxy_cache levels=2:1 keys_zone=itcast:200m inactive=1d max_size=20g;
upstream backend{
server 192.168.111.128:8080;
}
server {
listen 8080;
server_name localhost;
location / {
proxy_cache itcast;
proxy_cache_key itheima;
proxy_cache_min_uses 5;
proxy_cache_valid 200 5d;
proxy_cache_valid 404 30s;
proxy_cache_valid any 1m;
add_header nginx-cache "$upstream_cache_status";
proxy_pass http://backend/js/;
}
}
}Nginx缓存的清除
方式一:删除对应的缓存目录
rm -rf /usr/local/proxy_cache/......方式二:使用第三方扩展模块
ngx_cache_purge
(1)下载ngx_cache_purge模块对应的资源包,并上传到服务器上。
ngx_cache_purge-2.3.tar.gz(2)对资源文件进行解压缩
tar -zxf ngx_cache_purge-2.3.tar.gz(3)修改文件夹名称,方便后期配置
mv ngx_cache_purge-2.3 purge(4)查询Nginx的配置参数
nginx -V(5)进入Nginx的安装目录,使用./configure进行参数配置
./configure --add-module=/root/nginx/module/purge(6)使用make进行编译
make(7)将nginx安装目录的nginx二级制可执行文件备份
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold(8)将编译后的objs中的nginx拷贝到nginx的sbin目录下
cp objs/nginx /usr/local/nginx/sbin(9)使用make进行升级
make upgrade(10)在nginx配置文件中进行如下配置
server{
location ~/purge(/.*) {
proxy_cache_purge itcast itheima;
}
}Nginx设置资源不缓存
前面咱们已经完成了Nginx作为web缓存服务器的使用。但是我们得思考一个问题就是不是所有的数据都适合进行缓存。比如说对于一些经常发生变化的数据。如果进行缓存的话,就很容易出现用户访问到的数据不是服务器真实的数据。所以对于这些资源我们在缓存的过程中就需要进行过滤,不进行缓存。
Nginx也提供了这块的功能设置,需要使用到如下两个指令
proxy_no_cache
该指令是用来定义不将数据进行缓存的条件。
| 语法 | proxy_no_cache string ...; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location |
配置实例
proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;proxy_cache_bypass
该指令是用来设置不从缓存中获取数据的条件。
| 语法 | proxy_cache_bypass string ...; |
|---|---|
| 默认值 | — |
| 位置 | http、server、location |
配置实例
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;上述两个指令都有一个指定的条件,这个条件可以是多个,并且多个条件中至少有一个不为空且不等于"0",则条件满足成立。上面给的配置实例是从官方网站获取的,里面使用到了三个变量,分别是$cookie_nocache、$arg_nocache、$arg_comment
$cookie_nocache、$arg_nocache、$arg_comment
这三个参数分别代表的含义是:
$cookie_nocache
指的是当前请求的cookie中键的名称为nocache对应的值
$arg_nocache和$arg_comment
指的是当前请求的参数中属性名为nocache和comment对应的属性值案例演示下:
log_format params $cookie_nocache | $arg_nocache | $arg_comment;
server{
listen 8081;
server_name localhost;
location /{
access_log logs/access_params.log params;
add_header Set-Cookie 'nocache=999';
root html;
index index.html;
}
}案例实现
设置不缓存资源的配置方案
server{
listen 8080;
server_name localhost;
location / {
if ($request_uri ~ /.*\.js$){
set $nocache 1;
}
proxy_no_cache $nocache $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $nocache $cookie_nocache $arg_nocache $arg_comment;
}
}












