LEMON

记录站

0%

Nginx

Nginx原理介绍

1.1 Nginx 概述

Nginx是⼀一个开源且⾼高性能、可靠的HTTP中间件、代理理服务。

开源: 直接获取源代码

高性能: 支持海海量量并发

image-2020062420084954569

1.2 Nginx的优缺点

  • 优点

    • 高并发量
      • 根据官方给出的数据,能够支持高达 50000 个并发连接数的响应。
    • 内存消耗少
      • 处理静态文件,同样起web 服务,比apache 占用更少的内存及资源,所以它是轻量级的。
    • 简单稳定
      • 配置简单,基本在一个conf文件中配置,性能比较稳定,可以7*24小时长时间不间断运行。
    • 支持Rwrite重写规则
      • 能够根据域名、URL的不同, 将HTTP请求分发到不同的后端服务器群组。
    • 功能多,低成本
      • Nginx可以做高并发的负载均衡,且Nginx是开源免费的,如果使用F5等硬件来做负载均衡,硬件成本比较高。
  • 缺点

    • 动态处理差
      • Nginx处理静态文件好,耗费内存少,但是处理动态页面则很鸡肋
    • rewrite弱
      • 虽然Nginx支持rewrite功能,但是相比于Apache来说,Apache比nginx 的rewrite 要强大。

1.3 Nginx应用场景

静态处理

反向代理

负载均衡

资源缓存

安全防护

访问限制

访问认证

1.4 Nginx的进程模型

Nginx的启动方式有两种:

  • 单进程启动:

    • 此时系统中只有一个进程,这个进程既是master进程,也是worker进程。
  • 多进程启动:

    • 此时系统中有且仅有一个master进程,有多个worker进程,master进程主要是用来管理worker进程的。

Nginx有两种进程:

Master主进程:

  1. 接收客户端的请求,然后在将客户端的请求交给他下面的子进程,子进程返回处理结果后,再将处理结果返回给客户端
  2. 监控并管理子进程的运行状态,当子进程出现异常情况下退出后,自动生成新的子进程

Worker子进程:

  1. 将主进程的请求交给内核去处理,然后在继续接收主进程发来的请求,当内核处理完后,返回给子进程处理结果,然后子进程再将结果返回给主进程。
  2. Nginx子进程的数量一般我们会设置与当前服务器的CPU核心数一致,可以使用auto指令让Nginx跟进系统自动设置worker

image-20200621181846932

1.5 Nginx的组成逻辑图

image-20200624200849579

1.6 Nginx的模块是什么

Nginx之所以有如此多的特性和功能,就是因为有大量的第三方开发者为其开发第三方模块

image-20200624213430515

上图中都可以在nginx官方文档中查询,这里就不再叙述了~~

Nginx应用部署

1.1 进入 nginx 官网,下载

Nginx官方网站:http://nginx.org/

image-20200621205106691

1.2 安装Nginx依赖

安装 openssl、zlib

1
yum -y install make zlib zlib-devel gcc gcc-c++ libtool openssl openssl-devel pcre pcre-devel

1.3 安装Nginx并修改属主属祖

1
2
3
4
5
6
7
8
9
#解压
tar xf nginx-1.12.2.tar.gz -C /usr/src/ && cd /usr/src/nginx-1.12.2/

#配置、编译、安装
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install && cd

#修改属主属组
useradd -s /sbin/nologin -M nginx
chown -R nginx:nginx /usr/local/nginx/

编译参数解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 这三个模块是用来做四层负载转发的
--with-stream
--with-stream_ssl_module
--with-stream_realip_module

#指定安装位置
--prefix=/usr/local/nginx

#指定worker进程运行的用户和组
--user=nginx --group=nginx

#开启状态监听模块
--with-http_stub_status_module

#指向配置文件存放位置
--conf-path=/xxx/xxx/

#指向错误日志存放位置
--error-log-path=/xxx/xxx/

#指向pid文件存放位置
--pid-path=/xxx/xxx/

#启用rtsig模块支持(实时信号)
--with-rtsig_module

# 临时缓存⽂文件
--http-client-body-temp-path=/xxx/xxx/client_tem
--http-proxy-temp-path=/xxx/xxx/proxy_temp
--http-fastcgi-temp-path=/xxx/xxx/fastcgi_temp
--http-uwsgi-temp-path=/xxx/xxx/uwsgi_temp
--http-scgi-temp-path=/xxx/xxx/scgi_temp

#添加模块
--add-module=/xxx/xxx/

#启用select模块支持(一种轮询模式,不推荐在高载环境下使用)禁用:--without-select_module
--with-select_module

#启用ngx_http_ssl_module支持(使支持https请求,需已安装openssl)
--with-http_ssl_module

#启用ngx_http_xslt_module支持(过滤转换XML请求)
--with-http_xslt_module

#启用ngx_http_image_filter_module支持(传输JPEG/GIF/PNG 图片的一个过滤器)(默认为不启用,要用到gd库)
--with-http_image_filter_module

#启用ngx_http_gzip_static_module支持(在线实时压缩输出数据流)
--with-http_gzip_static_module

#启用ngx_http_degradation_module支持(允许在内存不足的情况下返回204或444码)
--with-http_degradation_module

#禁用ngx_http_access_module支持(该模块提供了一个简单的基于主机的访问控制,允许或拒绝基于ip地址)
--without-http_access_module

#禁用ngx_http_auth_basic_module(该模块是可以使用用户名和密码基于http基本认证方法,来保护你的站点或其部分内容)
--without-http_auth_basic_module

#禁用ngx_http_rewrite_module支持(该模块允许使用正则表达式改变URL)
--without-http_rewrite_module

#禁用ngx_http_fastcgi_module支持(该模块允许Nginx 与FastCGI 进程交互,并通过传递参数来控制FastCGI 进程工作。)
--without-http_fastcgi_module

1.4 设置防火墙规则

开放80端口号

1
2
3
4
5
6
7
8
9
查看开放的端口号
firewall-cmd --list-all

设置开放的端口号
firewall-cmd --add-service=http -permanent
sudo firewall-cmd --add-port=80/tcp -permanent

重启防火墙
firewall-cmd -reload

1.5 Nginx常用命令 及 信号

命令

image-20200624203124482

信号

image-202006242333124482

信号详解:

1、TERM,INT:nginx的主进程马上被关闭,不能完整处理正在使用的nginx的用户的请求,等同于 nginx -s stop。

2、QUIT:优雅的关闭nginx进程,在处理完所有正在使用nginx用户请求后再关闭nginx进程,等同于nginx -s quit。

3、HUP: nginx主进程不变,nginx进程不关闭,但是重新加载配置文件。等同于nginx -s reload。

4、USR1:不用关闭nginx进程就可以重读日志,此命令可以用于nginx的日志定时备份,按月/日等时间间隔分割有用。

5、USR2:nginx的版本需要升级的时候,不需要停止nginx,就能对nginx升级。

6、WINCH:配合USR2对nginx升级,优雅的关闭nginx旧版本的进程,

reload重载配置文件的过程

image-20200624211822429

image-20200624211822429

1.6 优化Nginx且编写启动脚本

两者做一个就行,当然也可以都做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Nginx软连接
ln -s /usr/local/nginx/sbin/* /usr/local/bin/

# Nginx启动脚本
cat <<EOF> /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

# 给予启动脚本执行权限
chmod u+x /lib/systemd/system/nginx.service

# 上述脚本解释
[Unit]:服务的说明
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置,注意:[Service]的启动、重启、停止命令全部要求使用绝对路径
Type=forking是后台运行的形式
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmp=True表示给服务分配独立的临时空间
[Install]运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为3

1.7 启动Nginx服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 删除nginx.conf配置文件所有的注释行和空行(这步可有可无)
sed -i /#.*/d /usr/local/nginx/conf/nginx.conf
sed -i /^$/d /usr/local/nginx/conf/nginx.conf

# 启动nginx
systemctl start nginx
systemctl enable nginx

# 查看状态
netstat -anptu|grep "nginx"
#####################################################################################################
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4827/nginx: master
#####################################################################################################

ps -aux|grep "nginx"
#####################################################################################################
root 4827 0.0 0.1 46108 1152 ? Ss 21:56 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 4830 0.0 0.1 46556 1936 ? S 21:56 0:00 nginx: worker process
root 4849 0.0 0.0 112676 980 pts/0 R+ 21:57 0:00 grep --color=auto nginx
#####################################################################################################

# 查看安装Nginx时的编译参数和版本
nginx -V
#####################################################################################################
nginx version: nginx/1.12.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module
#####################################################################################################

Nginx常用模块及内置变量

1.1 Nginx常用模块

Nginx模块分为 Nginx官方模块 以及 Nginx第三方模块

Nginx编译选项 模块作用
ngx_http_core_module 包含⼀些核心的http参数配置,对应Nginx的配置区块部分
ngx_http_access_module 访问控制模块,用来控制网站用户对Nginx的访问
ngx_http_gzip_module 压缩模块,对Nginx返回的数据压缩,属于性能优化模块
ngx_http_fastcgi_module fastci模块,和动态应用相关的模块,例如PHP
ngx_http_proxy_module proxy代理模块
ngx_http_upstream_module 负载均衡模块,可以实现网站的负载均衡功能及节点的健康检查。
ngx_http_rewrite_module URL地址重写模块
ngx_http_limit_conn_module 限制用户并发连接数及请求数模块
ngx_http_limit_req_module 限制Nginx request processing rate根据定义的key
ngx_http_log_module 访问日志模块,以指定的格式记录Nginx客户访问日志等信息
ngx_http_auth_basic_module Web认证模块,设置Web用户通过账号密码访问Nginx
nginx_http_ssl_module ssl模块,用于加密的http连接,如https

1.2 Nginx内置变量

http请求变量

Nginx内置变量

自定义变量

变量名 含义
$uri 当前请求的uri,不带参数
$request_uri 请求的uri,带完整参数
$host http请求报文中host首部,如果没有则以处理此请求的虚拟主机的主机名代替
$hostname nginx服务运行在主机的主机名
$remote_addr 客户端IP
$remote_port 客户端口
$remote_user 用户认证时客户端用户输入的用户名
$request_filename 用户请求中的URI经过本地root或alias转换后映射的本地文件路径
$request_method 请求方法, GET POST PUT
$server_addr 服务器地址
$server_port 服务器端口
$server_name 服务器名称
$server_protocol 服务器向客户端发送响应时的协议, 如http/1.1 http/1.0
$scheme 在请求中使用scheme, 如http://xxx.com中的http
$http_HEADER 匹配请求报文中指定的HEADER
$http_host 匹配请求报文中的host首部
$document_root 当前请求映射到的root配置

Nginx.conf 配置文件

1.1 Nginx配置文件语法

image-20200624202639852

1.2 配置文件整体结构

Nginx主配置文件 nginx.conf,整个配置文件是以区块的形式组织的;一般,每个区块以一对大括号 {} 来表示开始与结束。

  1. Main位于nginx.conf配置文件的最高层;Main层下可以有Event、HTTP层

  2. HTTP层下面允许有多个Server层, 用于对不同的网站做不同的配置

  3. Server层也允许有多个location, 用于对不同的路径资源进行不同模块的配置

image-20200621230154767

1.2.1 main全局块

配置影响nginx全局的指令。主要包括:

  • 配置运行Nginx服务器用户(组)
  • worker process数
  • Nginx进程
  • PID存放路径错误日志的存放路径
  • 配置文件的引入

1.2.2 events块

配置影响nginx服务器或与用户的网络连接。主要包括:

  • 设置网络连接的序列化
  • 是否允许同时接收多个网络连接
  • 事件驱动模型的选择
  • 最大连接数的配置

1.2.3 http块

可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。主要包括:

  • 定义MIMI-Type
  • 自定义服务日志
  • 允许sendfile方式传输文件
  • 连接超时时间
  • 单连接请求数上限

1.2.4 server块

配置虚拟主机的相关参数,一个http中可以有多个server。主要包括:

  • 配置网络监听
  • 基于名称的虚拟主机配置
  • 基于IP的虚拟主机配置

1.2.5 location块

配置请求的路由,以及各种页面的处理情况。主要包括:

  • location配置
  • 请求根目录配置更改
  • location的URI
  • 网站默认首页配置

1.3 Nginx的默认配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#### main全局块 ####
worker_processes 1; // nginx的worker工作进程,一般数值为cpu核数

#### events事件块 ####
events {
worker_connections 1024; // 每个后台worker process进程的最大并发连接数
}

#### http块 ####
http {
include mime.types; // 文件扩展名与类型映射表
default_type application/octet-stream; // 默认文件类型
sendfile on; // 开启高效传输模式,默认为off
keepalive_timeout 65; // 连接超时时间,单位是秒

#### server块 ####
server {
listen 80; // 监听端口
server_name localhost; // 提供服务的域名或主机名

#### location块 ####
location / {
root html; // 存放网站路径
index index.html index.htm; // 默认访问首⻚文件
}
// 指定错误代码, 统一定义错误页面, 错误代码重定向到新的 Locaiton资源上
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

Nginx日志文件详解

1.1 Nginx日志配置

在学习日志之前, 我们需要先了解下HTTP请求和返回

1
curl -v https://www.baidu.com

image-20200621232120269

log_format语法格式及参数语法说明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
### 配置语法: 包括: error.log access.log ###
Syntax: log_format <NAME> <String>;
Default: log_format combined "...";
Context: http

### Nginx默认日志格式 ###
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

### Nginx日志变量解释 ###
log_format
$remote_addr #记录访问网站的客户端地址
$remote_user #nginx认证用户名
$time_local #记录访问时间与时区
$request #用户的http请求行, GET等方法、http协议版本
$status #http状态码,记录请求返回的状态码,例如:200、301、404等
$body_bytes_sent #服务器发送给客户端的响应body字节数大小,默认为B(byte)
$http_referer #记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置。
$http_user_agent #记录客户端访问信息,例如:浏览器、手机客户端等
$http_x_forwarded_for #当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置

1.2访问日志段分析

摘出来一段部分结果:

1
120.4.15.223 - lemon [22/Jun/2020:12:01:43 +0800] "GET /index.php/archives/56/ HTTP/1.1" 200 4865 "http://www.lemon-li.cn/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0" "-"

各个字段所对应的变量

1
2
3
4
5
6
7
8
9
192.168.2.254                            //$remote_addr
lemon //$remote_user
[22/Jun/2020:12:01:43 +0800] //$time_local
"GET /index.php/archives/56/ HTTP/1.1" //$request
200 //$status
4865 //$body_bytes_sent
"http://www.lemon-li.cn/" //$http_referer
"Mozilla/5.0 (Windows xx Firefox/77.0" //$http_user_agent
"-" //$http_x_forwarded_for

1.3 Nginx访问日志统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
##统计tcp连接数
netstat -anpt|awk 'NR>=3{print $6}'|sort -rn|uniq -c

##统计访问日志中访问量最多的10个IP地址, 这下面两个都行
awk '{print $1}' /usr/local/nginx/logs/access.log | sort | uniq -c | sort -nr -k1 | head -n 10
cat /usr/local/nginx/logs/access.log|awk '{a[$1]++} END {for(b in a) print b"\t"a[b]}'|sort -k2 -r|head -n 10

##统计HTTP状态码次数
awk '{S[$9]++};END{for(i in S) {print S[i],i}}' /usr/local/nginx/logs/access.log|sort -nr|head

##注解:
awk '{ print $1}':取数据的低1域(第1列)。
sort:对IP部分进行排序。
uniq -c:打印每一重复行出现的次数。(并去掉重复行)。
sort -nr -k1:按照重复行出现的次序倒序排列,-k1以第一列为标准排序。
head -n 10:取排在前5位的IP 。

1.4 http_access_module局限性

下图是没有使用 http_x_forwarded_for 记录真实客户端IP地址以及代理服务器IP

image-20200623102751786

下图是使用 http_x_forwarded_for 记录真实客户端IP地址以及代理服务器IP

image-20200623104731498

解决方式

  1. 采用HTTP头信息控制访问, 代理以及web服务开启 http_x_forwarded_for

  2. 结合geo模块作

  3. 通过HTTP自动以变量传递

Nginx常用的基本配置

1.1 Nginx 虚拟主机

所谓虚拟主机,在web服务器里就是一个独立的网站 站点,这个站点对应独立的域名(也可能是IP或端口),具有独立的程序及资源目录,可以独立地对外提供服务供用户访问。

1.1.1 配置基于域名虚拟主机(最常用的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1.创建web站点⽬目录
[root@nginx conf]# mkdir -p /soft/code/{www,bbs}
[root@nginx conf]# echo "www" > /soft/code/www/index.html
[root@nginx conf]# echo "bbs" > /soft/code/bbs/index.html
[root@nginx conf]# tree /soft/
/soft/
└── code
├── bbs
│   └── index.html
└── www
└── index.html

2.配置虚拟主机
[root@nginx conf]# cat vhosts/{www,bbs}.conf
server {
listen 80;
server_name www.lemon-li.cn;
root /soft/code/www;
index index.html;
...
}
server {
listen 80;
server_name bbs.lemon-li.cn;
root /soft/code/bbs;
index index.html;
...
}

3.访问
[root@nginx conf]# curl www.lemon-li.cn
www

[root@nginx conf]# curl bbs.lemon-li.cn
bbs

1.1.2 配置不同端口访问不同虚拟主机

1
2
3
4
5
6
7
8
9
10
11
12
// 仅修改 listen 监听端口即可 , 但不能和系统端口发生冲突!
server {
...
listen 8001;
...
}

server {
...
listen 8002;
...
}

1.1.3 配置虚拟主机别名

所谓虚拟主机别名,就是虚拟主机设置除了主域名以外的一个域名,实现用户访问的多个域名对应同一个虚拟主机网站的功能

这里以bbs.lemon-li.cn域名的虚拟主机为例,为其增加一个别名lemon.com时,出现网站内容和访问bbs.lemon-li.cn是一样的

具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 默认配置
[root@nginx conf]# vim /etc/nginx/nginx.conf
server {
listen 80;
server_name bbs.lemon-li.cn;
...
}

// 别名配置
[root@nginx conf]# vim /etc/nginx/nginx.conf
server {
listen 80;
server_name bbs.lemon-li.cn lemon-li-cn;
...
}

// 使用 Linux 下 curl 测试结果
[root@nginx conf]# curl lemon-li.cn
bbs.lemon-li.cn

[root@nginx conf]# curl bbs.lemon-li.cn
bbs.lemon-li.cn

// 访问带 bbs 和不带 bbs 是一样的, 当然除了别名实现也可以通过 rewrite 实现

1.2 Nginx 状态监控

–with-http_stub_status_module 记录 Nginx 客户端基本访问状态信息

默认用法:

1
2
3
Syntax: stub_status;
Default: off
Context: server, location

具体配置:

1
2
3
4
location /status {
stub_status on;
access_log off;
}

提供了以下状态信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Active connections: 1
## Nginx 当前活跃连接数, 有多少人在请求

server accepts handled requests
1 1 1
## server表示Nginx处理接收握⼿总次数。
## accepts表示Nginx处理接收总连接数。
## 请求丢失数=(握⼿数-连接数)可以看出,本次状态显示没有丢失请求。
## handled requests,表示总共处理了了1次请求。

Reading: 0 Writing: 1 Waiting: 0
## Reading表示Nginx读取数据
## Writing表示Nginx写的情况
## Waiting表示Nginx开启keep-alive长连接情况下, 既没有读也没有写, 建立连接情况

使用ab命令测试压力

1
2
3
4
ab -c 10 -n 100 http://192.168.2.1:80/index.html
-c 并发数
-n 总的请求数
-k 是否开启长连接

访问查看

image-20200622162405702

1.3 Nginx下载站点

Nginx默认是不允许列出整个目录浏览下载的 !

默认用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Syntax: autoindex on | off;
Default: off;
Context: http, server, location

//autoindex常⽤用参数
autoindex_exact_size off;
默认为on, 显示出文件的确切大小,单位是bytes。
修改为off,显示出文件的大概大小,单位是kB或者MB或者GB。

autoindex_localtime on;
默认为off,显示的文件时间为GMT时间。
修改为on, 显示的文件时间为文件的服务器时间。

charset utf-8,gbk;
默认中文目录乱码,添加上解决乱码。

具体配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
//开启目录浏览
location / {
root /download;
autoindex on;
charset utf-8,gbk;
autoindex_localtime on;
autoindex_exact_size off;
}

//创建站点资源
[root@nginx /]# mkdir -p /download
[root@nginx /]# cd download/
[root@nginx download]# touch lemon{1..20}.txt

展示效果:

image-20200624125401798

1.4 Nginx 访问控制

基于IP的访问控制 http_access_module

基于⽤用户登陆认证 http_auth_basic_module

1.4.1 基于IP的访问控制

语法格式如下:

1
2
3
4
5
6
7
8
9
// 允许配置语法
Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except

// 拒绝配置语法
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except

具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 配置拒绝某一个 IP, 其他全部允许
location /status {
deny 192.168.2.254;
allow all;
stub_status on;
access_log off;
}

// 只允许某一个网段访问 , 其它全部拒绝
location /status {
allow 192.168.2.0/24;
deny all;
stub_status on;
access_log off;
}

1.4.2 基于用户登陆认证

语法格式如下:

1
2
3
4
5
6
7
8
9
// 配置语法
Syntax: auth_basic string | off;
Default: auth_basic off;
Context: http, server, location, limit_except

// ⽤户密码记录配置文件
Syntax: auth_basic_user_file file;
Default: —
Context: http, server, location, limit_except

具体配置如下:

1
2
3
4
5
6
7
8
9
// 需要安装依赖组件
[root@nginx ~]# yum install httpd-tools
[root@nginx ~]# htpasswd -c /usr/local/nginx/conf/user.conf lemon
[root@nginx ~]# cat /usr/local/nginx/conf/user.conf
lemon:$apr1$TLvI5fjG$vOFaI7v3AxSFD/M/NO3TP/

// 可在 http,server,location 里添加如下信息
auth_basic "Auth access Blog Input your Passwd!";
auth_basic_user_file /usr/local/nginx/conf/user.conf;

1.4.3 上面两者也可以一起用

1
2
3
4
5
//想对哪个网页进行加密就在哪个里面加入以下配置:
auth_basic "Auth access Blog Input your Passwd!";
auth_basic_user_file /usr/local/nginx/conf/user.conf;
allow 192.168.2.254;
deny all;

1.5 Nginx 访问限制

1.5.1 http协议的连接与请求

HTTP是建立在TCP, 在完成HTTP请求需要先建立TCP三次握手(称为TCP连接),在连接的基础上在HTTP请求。

image-20200622000823214

1.5.2 HTTP 协议的连接与请求

  • HTTP 请求建立在一次 TCP 连接基础上

  • 一次 TCP 请求至少产生一次 HTTP 请求

HTTP协议版本 连接关系
HTTP1.0 TCP不能复用
HTTP1.1 顺序性TCP复用
HTTP2.0 多路复用TCP复用

1.5.3 Nginx 连接限制

连接频率限制 limit_conn_module

连接限制语法:

image-20200622000823214

image-20200624225455880

具体配置如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http {
//http 段配置连接限制 , 同一时刻只允许一个客户端 IP 连接
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;
...
server {
...
location / {
// 限制向客户端返回的速度,每秒钟速率50字节,这个配置仅仅只是为了能看到效果
limit_rate 50;
// 同一时刻只允许一个客户端 IP 连接
limit_conn conn_zone 1;
// 修改限制发生时向客户端返回的错误码,可做可不做
limit_conn_status 500;
// 修改限制发生时的日志级别,可做可不做
limit_conn_log_level warn;
...
}
}
}

打开两个终端同时请求

1
curl http://ttk.lemon-li.cn/

image-20200624231652524

image-20200624231848233

1.5.4 Nginx 请求限制

请求频率限制 limit_req_module

请求限制语法:

image-20200624231848233

image-20200624231848233

具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
http {
//http 段配置请求限制, rate 限制速率,限制一秒钟最多一个 IP 请求
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;
...
server {
...
location / {
// 1r/s 内只接收一个请求, 剩下的将被延迟处理, 请求数超过 burst 定义的数量, 多余请求拒绝处理并返回503错误码给客户端
limit_req zone=req_zone burst=3 nodelay;
...
}
}
}

ab压力测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
ab -c 10 -n 100 http://192.168.2.1:80/index.html


Benchmarking ttk.lemon-li.cn (be patient).....done


Server Software: nginx
Server Hostname: ttk.lemon-li.cn
Server Port: 80

Document Path: /
Document Length: 25 bytes

Concurrency Level: 20
Time taken for tests: 0.033 seconds
Complete requests: 50
Failed requests: 46 # 可以看到这里,失败了46次,也就是说50次请求只成功了4次,也就是1 + 3 = 4
(Connect: 0, Receive: 0, Length: 46, Exceptions: 0)
Write errors: 0
Non-2xx responses: 46
Total transferred: 18062 bytes
HTML transferred: 9576 bytes
Requests per second: 1503.17 [#/sec] (mean)
Time per request: 13.305 [ms] (mean)
Time per request: 0.665 [ms] (mean, across all concurrent requests)
Transfer rate: 530.28 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 3 4 0.6 4 5
Processing: 3 4 0.6 4 5
Waiting: 3 4 0.6 4 5
Total: 6 8 1.1 8 10

Percentage of the requests served within a certain time (ms)
50% 8
66% 8
75% 9
80% 9
90% 9
95% 9
98% 10
99% 10
100% 10 (longest request)

使用浏览器测试狂点刷新5次就会报503

image-20200621205106691

查看错误日志信息

1
2020/06/24 16:27:04 [error] 960#0: *1903 limiting requests, excess: 3.486 by zone "req_zone", client: 101.200.227.38, server: ttk.lemon-li.cn, request: "GET / HTTP/1.0", host: "ttk.lemon-li.cn"

1.5.5 整体总结

连接限制 没有 请求限制有效?

  • 前面说过, 多个请求可以建立在一次的TCP连接之上, 那么我们对请求的精度限制,当然比对一个连接的限制会更加的有效。

  • 因为同一时刻只允许一个连接请求进入。

  • 但是同一时刻多个请求可以通过一个连接进入。

  • 所以请求限制才是比较合理的限制解决方案。

1.6 Nginx日志分割

技术要点:

  1. 剪切日志后,使用 kill -USR1 发送信号重新生成日志文件,同时还不影响网站请求处理进程。

  2. 错误时通过echo和tee -a命令将错误显示的同时写入到日志文件/var/log/messages。

1.6.1 手动日志分割

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 查看nginx日志文件
[root@nginx ~]# ll -h /usr/local/nginx/logs/
总用量 60K
-rw-r--r-- 1 root root 52K 625 00:41 access.log
-rw-r--r-- 1 root root 478 625 00:39 error.log
-rw-r--r-- 1 root root 4 625 00:33 nginx.pid

// 先备份日志文件
[root@nginx logs]# pwd
/usr/local/nginx/logs
[root@nginx logs]# cp access.log access.log.bak
[root@nginx logs]# ll -h
总用量 60K
-rw-r--r-- 1 nginx root 52K 625 00:51 access.log
-rw-r--r-- 1 root root 52K 625 00:41 access.log.bak
-rw-r--r-- 1 nginx root 829 625 00:52 error.log
-rw-r--r-- 1 root root 4 625 00:33 nginx.pid

// 手动执行日志切割命令 或 发送信号
[root@nginx logs]# nginx -s reopen
[root@nginx logs]# ll -h
总用量 60K
-rw-r--r-- 1 nginx root 0 625 00:51 access.log
-rw-r--r-- 1 root root 52K 625 00:41 access.log.bak
-rw-r--r-- 1 nginx root 829 625 00:52 error.log
-rw-r--r-- 1 root root 4 625 00:33 nginx.pid

1.6.2 自动日志分割

就是写一个脚本,然后放到计划任务当中按时间自动切割日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 编写日志切割脚本
[root@nginx ~]# vi /root/cut_nginx_log.sh
#!/bin/bash
datetime=$(date -d "-1 day" "+%Y%m%d")
log_path="/usr/local/nginx/logs"
pid_path="/usr/local/nginx/logs/nginx.pid"
mkdir -p $log_path/backup
if [ -f $pid_path ];then
mv $log_path/access.log $log_path/backup/access.log-$datetime
kill -USR1 $(cat $pid_path) #USR1通常被用来告知应用程序重载配置文件
find $log_path/backup -mtime +30 | xargs rm -f
else
echo "Error,Nginx is not working!" >> /var/log/messages
fi

// 给予脚本执行权限
[root@nginx ~]# chmod +x /root/cut_nginx_log.sh

//添加至计划任务,每天的00:00点执行
[root@nginx ~]# echo "0 0 * * * /root/cut_nginx_log.sh" >> /var/spool/cron/root
[root@nginx ~]# crontab –l

//手动执行一下这个脚本验证下效果
[root@nginx ~]# bash -x /root/cut_nginx_log.sh
++ date -d '-1 day' +%Y%m%d
+ datetime=20200624
+ log_path=/usr/local/nginx/logs
+ pid_path=/usr/local/nginx/logs/nginx.pid
+ mkdir -p /usr/local/nginx/logs/backup
+ '[' -f /usr/local/nginx/logs/nginx.pid ']'
+ mv /usr/local/nginx/logs/access.log /usr/local/nginx/logs/backup/access.log-20200624
++ cat /usr/local/nginx/logs/nginx.pid
+ kill -USR1 968
+ find /usr/local/nginx/logs/backup -mtime +30
+ xargs rm -f

// 查看日志是否被切割及备份
[root@nginx ~]# ls /usr/local/nginx/logs/backup/
access.log-20200624

1.7 Nginx平滑升级部署

  • 作用:在不影响客户端业务的情况下升级Nginx服务
  • 切记,这里一定要使用绝对路径启动Nginx,才能够作热升级

image-20200624212307459

Nginx信号详解:

1
2
3
4
5
6
1.TERM,INT:nginx的主进程马上被关闭,不能完整处理正在使用的nginx的用户的请求,等同于 nginx -s stop。
2.QUIT:优雅的关闭nginx进程,在处理完所有正在使用nginx用户请求后再关闭nginx进程,等同于nginx -s quit。
3.HUP: nginx主进程不变,nginx进程不关闭,但是重新加载配置文件。等同于nginx -s reload。
4.USR1:不用关闭nginx进程就可以重读日志,此命令可以用于nginx的日志定时备份,按月/日等时间间隔分割有用。
5.USR2:nginx的版本需要升级的时候,不需要停止nginx,就能对nginx升级。
6.WINCH:配合USR2对nginx升级,优雅的关闭nginx旧版本的进程

image-20200624212511817

具体操作如下:

  • 当前版本为:nginx-1.12.2
  • 升级版本为:nginx-1.16.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 查看旧的nginx都编译了什么模块,一会编译新版本时就照着加就行了
[root@nginx ~]# nginx -V
nginx version: nginx/1.12.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module

// 查看旧版本nginx的后台进程PID,一会升级nginx时会用到
[root@nginx ~]# ps -aux|grep nginx
root 2241 0.0 0.1 56316 1156 ? Ss 01:53 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 2242 0.0 0.1 56700 1932 ? S 01:53 0:00 nginx: worker process

// 备份旧nginx的二进制命令文件
[root@nginx ~]# cp -r /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
[root@nginx ~]# ll /usr/local/nginx/sbin/
总用量 14888
-rwxr-xr-x 1 nginx nginx 7621776 621 21:53 nginx
-rwxr-xr-x 1 root root 7621776 625 02:01 nginx.old

// 准备nginx-1.16.1源码包
[root@nginx ~]# wget http://nginx.org/download/nginx-1.16.1.tar.gz

// 解压、配置、编译nginx-1.16.1源码包。注:#不能加make install,如若添加,则覆盖了!
[root@nginx ~]# tar xf nginx-1.16.1.tar.gz -C /usr/src/
[root@nginx ~]# cd /usr/src/nginx-1.16.1/
[root@nginx nginx-1.16.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module && make

// 进入编译好的objs目录中将编译好的nginx1.16.1的二进制命令文件拷贝至对应位置
[root@nginx nginx-1.16.1]# cd objs/ && ll
总用量 7976
-rw-r--r-- 1 root root 18617 625 01:55 autoconf.err
-rw-r--r-- 1 root root 56144 625 01:55 Makefile
-rwxr-xr-x 1 root root 7961952 625 01:56 nginx
-rw-r--r-- 1 root root 5341 625 01:56 nginx.8
-rw-r--r-- 1 root root 7651 625 01:55 ngx_auto_config.h
-rw-r--r-- 1 root root 657 625 01:55 ngx_auto_headers.h
-rw-r--r-- 1 root root 9435 625 01:55 ngx_modules.c
-rw-r--r-- 1 root root 93664 625 01:56 ngx_modules.o
drwxr-xr-x 9 root root 91 625 01:55 src
[root@nginx objs]# cp -rf nginx /usr/local/nginx/sbin/
cp:是否覆盖"/usr/local/nginx/sbin/nginx"? y
[root@nginx objs]# ll /usr/local/nginx/sbin/
总用量 15220
-rwxr-xr-x 1 root root 7961952 625 02:04 nginx
-rwxr-xr-x 1 root root 7621776 625 02:01 nginx.old

// 开始使用信号实现热升级nginx
## 发送 USR2 信号,向主进程( master)发送 USR2 信号,Nginx 会启动一个新版本的 master 进程和对应工作进程,和旧版一起处理请求。
[root@nginx objs]# kill -USR2 2241
[root@nginx objs]# ps -aux|grep nginx
root 2241 0.0 0.1 56316 1340 ? Ss 01:53 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 2242 0.0 0.1 56700 1932 ? S 01:53 0:00 nginx: worker process #老版本进程
root 5361 0.0 0.3 56348 3336 ? S 02:07 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 5362 0.0 0.1 56744 1928 ? S 02:07 0:00 nginx: worker process #新版本进程

[root@nginx objs]# kill -WINCH 2242 # 关闭老版本进程的worker进程
[root@nginx objs]# ps -aux|grep nginx
root 2241 0.0 0.1 56316 1340 ? Ss 01:53 0:00 nginx: master process /usr/local/nginx/sbin/nginx
root 5361 0.0 0.3 56348 3336 ? S 02:07 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 5362 0.0 0.1 56744 1928 ? S 02:07 0:00 nginx: worker process
nginx 5366 0.0 0.1 56700 1928 ? S 02:10 0:00 nginx: worker process #这是关掉老版本woker之后新生成的woker进程

[root@nginx objs]# kill -QUIT 2241 # 关闭老版本进程的master进程
[root@nginx objs]# ps -aux|grep nginx
root 5361 0.0 0.3 56348 3336 ? S 02:07 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 5362 0.0 0.1 56744 1928 ? S 02:07 0:00 nginx: worker process

[root@nginx objs]# nginx -V # 至此,nginx就算是热升级成功了
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module

1.8 index 和 autoindex的区别

index模块

image-20200624212307459

autoindex模块

image-20200624212307459

autoindex 主要有下面四个指令:

image-20200625013255522

1.9 root 和 alias 的区别(重点)

root属性指定的值是要加入到最终路径的,所以访问的位置变成了 root的值/locaiton的值。而我不想把访问的URI加入到路径中。所以就需要使用alias属性,其会抛弃URI,直接访问alias指定的位置

1.9.1 root属性

结论: root属性,会把root的值(这里是yyy)加入到访问路径(locaition)之前

1
2
3
location xxx {
root yyy
}

浏览器访问 http://URL/aaa.html,实际访问的是 http://URL/yyy/xxx/aaa.html

浏览器访问 http://URL/xxx/abc.html,实际访问的是 http://URL/yyy/xxx/abc.html

浏览器访问 http://URL/xxx/ccc/abc.html,实际访问的是 http://URL/yyy/xxx/ccc/abc.html

1.9.2 alias属性(别名)

结论:alias属性,会把alias的值(这里是yyy)替代访问路径匹配的部分(这里是xxx)

1
2
3
4
locaiton xxx {
# alias必须以 / 结束,否则无效!!!
alias /yyy/;
}

浏览器访问 http://URL/xxx.html,实际访问的是 http://URL/yyy/xxx.html

浏览器访问 http://URL/xxx/abc.html,实际访问的是 http://URL/yyy/abc.html

浏览器访问 http://URL/xxx/ccc/abc.html,实际访问的是 http://URL/yyy/ccc/abc.html

1.10 定义错误页面

模块:error_page,作用是根据客户端的访问网站的返回状态码,为其指定到特定的错误页面

语法:

1
error_page code [ code... ] [ = | =answer-code ] uri | @named_location 

简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 编写错误页面
echo 'client_4xx_error' > /www/test/400_error.html
echo 'client_5xx_error' > /www/test/500_error.html

// 定义客户端错误页面
error_page 400 401 402 403 404 /400_error.html;
location /400_error.html {
root /www/test;
}

// 定义服务端错误页面
error_page 500 501 502 503 504 /500_error.html;
location /500_error.html {
root /www/test;
}

验证一下效果

image-20200625104239563

image-20200625104314946

image-20200625104456679

1.11 设置Nginx防盗链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
zhen主机配置防盗链
[root@zhen ~]# vi /usr/local/nginx/conf/nginx.conf
在server{}区域里添加以下配置:
location ~* \.(wma|wmv|asf|mp3|mmf|zip|rar|gif|png|swf|flv|jpeg) {
valid_referers nonde blocked *.zhen.com zhen.com;
if ($invalid_referer) {
rewrite ^/ http://www.zhen.com/error.jpg;
}
}
#注意:不能存在以下缓存配置:
55 location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
56 expires 1d;
57 }
wq!
[root@zhen html]# systemctl restart nginx
解释:
第一行: wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv 表示对这些后缀的文件进行防盗链。
第二行:valid_referers表示被允许的URL,none表示浏览器中 referer(Referer 是 header 的一部分,当浏览器向 web 服务器发送请求时,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理) 为空的情况,就直接在浏览器访问图片,blocked referer 不为空的情况,但是值被代理或防火墙删除了,这些值不以http://或 https://开头,*.zhen是匹配URL的域名。
第三行:if{}判断如果是来自于invalid_referer(不被允许的URL)链接,即不是来自第二行指定的URL,就强制跳转到错误页面,当然直接返回 404 (return 404)也是可以的,也可以是图片。
注意:防盗链测试时,不要和expires配置一起使用。

1.12 如何在已经安装好的nginx中添加模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 原已经安装好的nginx,现在需要添加一个未被编译安装的模块:

// 查看原来编译时都带了哪些参数
# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.12.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
configure arguments: --prefix=/usr/local/nginx --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre

进入nginx源码目录
# cd nginx-1.12.2

// 添加的参数 (要加之前已经过的编译模块,不然最后只有新编译模块)
# ./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-http_ssl_module

// 编译,make完之后在objs目录下就多了个nginx,这个就是新版本的程序了。注意 {不要make install,否则就是覆盖安装}
# make

// 替换nginx二进制文件
# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak (备份之前的nginx二进文件)
# cp ./objs/nginx /usr/local/nginx/sbin/

// 测试新的nginx程序是否正确
# /usr/local/nginx/sbin/nginx -t
nginx: theconfiguration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx:configuration file /usr/local/nginx/conf/nginx.conf test issuccessful

// 重新加载nginx
# /usr/local/nginx/sbin/nginx -s reload

// 查看ngixn版本极其编译参数
# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.12.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-http_ssl_module

1.13 Nginx中的location指令(重点)

location的作用是根据用户请求的URI来执行不同的应用,就是根据用户请求的网站URL进行匹配,匹配成功即进行相关的操作

1.13.1 安装第三方的模块

  • 下载第三方模块echo
1
[root@nginx ~]# wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz
  • 重新编译添加三方echo模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@nginx ~]# nginx -V
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module

[root@nginx ~]# tar -xf v0.61.tar.gz -C /usr/src/
[root@nginx ~]# cd /usr/src/nginx-1.16.1/
[root@nginx nginx-1.16.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/src/echo-nginx-module-0.61/ && make
[root@nginx nginx-1.16.1]# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
[root@nginx nginx-1.16.1]# cp -rf objs/nginx /usr/local/nginx/sbin/

[root@nginx nginx-1.16.1]# nginx -V
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/src/echo-nginx-module-0.61/

1.13.2 location语法 及 符号规则

  • location语法格式:
1
2
3
4
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
Syntax: location @name { ... }
Default: —
Context: server, location
  • location的符号:
符号 说明
= 表示精确匹配
^~ 表示uri以指定字符或字符串开头
~ 表示区分大小写的正则匹配
~* 表示不区分大小写的正则匹配
/ 通用匹配,任何请求都会匹配到
  • 注意事项:
1
2
3
4
5
6
7
8
有些资料上介绍location支持 不匹配 !~,
如: location !~ 'png'{ ... }
这是错误的,location不支持 !~

如果有这样的需求,可以通过if来实现,
如: if ($uri !~ 'png') { ... }

注意:location优先级小于if

1.13.4 location优先级及案例

总结一句话:= 符号优先级最高,/ 符号优先级最低

  • 规则优先级:
1
=  高于  ^~  高于  ~* 等于 ~  高于  /
  • 对比 / 和 ~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
示例1:
server {
listen 80;
server_name location;

location /abc {
echo '/';
}

location ~ abc {
echo '~';
}
}

测试命令:curl http://127.0.0.1/abc/1.html
结果是:~
  • 对比 ~ 和 ~*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
示例1:
server {
listen 80;
server_name location;
root html;

location ~ /abc {
echo '~';
}

location ~* /abc {
echo '~*';
}
}
测试命令:curl http://127.0.0.1/abc/1.html
结果是:~

示例2:把他们两个的顺序调整一下
server {
listen 80;
server_name location;
root html;

location ~* /abc {
echo '~*';
}

location ~ /abc {
echo '~';
}
}
测试命令:curl http://127.0.0.1/abc/1.html
结果是:~*
结论是:~和~*优先级其实是一样的,如果两个同时出现,配置文件中哪个location靠前,哪个生效。
  • 对比 ^~ 和 ~

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    示例1:
    server {
    listen 80;
    server_name location;
    root html;

    location ~ /abc {
    echo '~';
    }

    location ^~ /abc {
    echo '^~';
    }
    }

    测试命令:curl http://127.0.0.1/abc/1.html
    结果是:^~
  • 对比 = 和 ^~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
示例1:
server {
listen 80;
server_name location;
root html;

location ^~ /abc.html {
echo '^~';
}

location = /abc.html {
echo '=';
}
}

测试命令:curl http://127.0.0.1/abc.html
结果是:=

Nginx静态资源控制

1. 静态资源类型

Nginx 作为静态资源 Web 服务器部署配置, 传输非常的高效, 常常用于静态资源处理, 请求, 动静分离

image-20200625134655267

非服务器动态运行 生成的文件就属于静态资源!

  • 静态资源:可以理解为前端的固定页面,这里面包含HTML、CSS、JS、图片等等,不需要查数据库也不需要程序处理,直接就能够显示的页面,如果想修改内容则必须修改页面,但是访问效率相当高。

  • 动态资源:需要程序处理或者从数据库中读数据,能够根据不同的条件在页面显示不同的数据,内容更新不需要修改页面但是访问速度不及静态页面。

类型 种类
浏览器端渲染 HTML、CSS、JS
图片 JPEG、GIF、PNG
音频 FLV、Mp4
文件 TXT、任意下载文件

2. 静态资源基本配置

2.1 文件读取高效 sendfile

作用简介:

sendfile可以让Nginx在传输文件时直接在磁盘和tcp socket之间传输数据;开启这个参数后可以让数据不用经过用户buffer。如果这个参数不开启,会先在用户空间(Nginx进程空间)申请一个buffer,用read函数把数据从磁盘读到cache,再从cache读取到用户空间的buffer,再用write函数把数据从用户空间的buffer写入到内核的buffer,最后到tcp socket。

语法格式:

1
2
3
Syntax: sendfile on | off;
Default: sendfile off;
Context: http, server, location, if in location

2.2 提高网络传输效率 tcp_nopush

作用简介:

告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。就是说数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞。

语法格式:

1
2
3
Syntax: tcp_nopush on | off;
Default: tcp_nopush off;
Context: http, server, location

2.3 与 tcp_nopush 对应的配置 tcp_nodelay

作用简介:

告诉nginx不要缓存数据,而是一段一段的发送—当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值。作用: 在keepalive连接下,提高网络的传输 ‘实时性’

语法格式:

1
2
3
Syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location

2.4 注意事项

  1. tcp_nopush配置 与 tcp_nodelay 互斥。

  2. 在nginx中tcp_nopush必须和sendfile配合使用。

3. 静态资源文件压缩配置

Nginx 将响应报文发送至客户端之前可以启用压缩功能,这能够有效的节约带宽,并提高响应至客户端的速度。

image-20200625215739171

3.1 gzip 压缩配置语法

1
2
3
4
5
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location

作用: 数据传输时压缩

3.2 gzip 压缩比率配置语法

1
2
3
4
5
Syntax: gzip_comp_level level;
Default: gzip_comp_level 1;
Context: http, server, location

作用: 压缩本身比较耗费服务端性能

3.3 gzip 压缩协议版本

1
2
3
4
5
Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location

作用: 压缩使用在http哪个协议, 主流版本1.1

3.4 图片压缩案例(不建议开启图片压缩)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@lemon-min vhosts]# mkdir -p /www/images
[root@lemon-min vhosts]# cat ttl.lemon-li.cn.conf
server {
listen 80;
server_name ttl.lemon-li.cn;
access_log logs/ttl_logs/access_ttl.lemon.cn.log main;
error_log logs/ttl_logs/error_ttl.lemon.cn.log info;
location ~ .*\.(gif|jpg|jpeg)$ {
root /www/images;
sendfile on;
gzip on;
gzip_comp_level 2;
gzip_http_version 1.1;
gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss text/javascript application/x-httpd-php image/jpeg image/gif image/png;
}
}

image-20200625225001698

没有开启 gzip 图片压缩时

image-20200625225811631

开启 gzip 图片压缩时(关于图片的压缩比率不是太过明显)

image-20200625230007749

3.5 文本压缩案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@lemon-min vhosts]# mkdir -p /www/doc
[root@lemon-min vhosts]# for i in {1..20000};do echo "asdabnvfgf" >> /www/doc/test.txt ; done
[root@lemon-min vhosts]# ll -h /www/doc/
总用量 216K
-rw-r--r-- 1 root root 215K 6月 25 23:15 test.txt
[root@lemon-min vhosts]# cat ttl.lemon-li.cn.conf
server {
listen 80;
server_name ttl.lemon-li.cn;
access_log logs/ttl_logs/access_ttl.lemon.cn.log main;
error_log logs/ttl_logs/error_ttl.lemon.cn.log info;
location ~ .*\.(txt|xml)$ {
root /www/doc;
sendfile on;
gzip on;
gzip_comp_level 2;
gzip_http_version 1.1;
gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss text/javascript application/x-httpd-php image/jpeg image/gif image/png;
}
}

没有启用 gzip 文件压缩时

image-20200625231806340

启用 gzip 文件压缩时(可见压缩的重要性)

image-20200625231931243

4. 静态资源浏览器缓存

HTTP协议定义的缓存机制 (如: Expires; Cache-control 等)

1、浏览器无缓存

浏览器请求->无缓存->请求WEB服务器->请求响应->呈现

2、浏览器有缓存

浏览器请求->有缓存->校验过期->是否有更新->呈现

校验是否过期 Expires HTTP1.0, Cache-Control(max-age) HTTP1.1

协议中Etag头信息校验 Etag ()

Last-Modified头信息校验 Last-Modified (具体时间)

1.缓存配置语法 expires

1
2
3
4
Syntax: expires [modified] time;
expires epoch | max | off;
Default: expires off;
Context: http, server, location, if in location

2.配置静态资源缓存

1
2
3
4
5
6
7
8
9
location ~ .*\.(js|css|html)$ {
root /soft/code/js;
expires 1h;
}

location ~ .*\.(jpg|gif|png)$ {
root /soft/code/images;
expires 1d;
}

3.开发代码没有正式上线时, 希望静态文件不被缓存

1
2
3
4
5
//取消js css html等静态文件缓存
location ~ .*\.(css|js|swf|json|mp4|htm|html)$ {
add_header Cache-Control no-store;
add_header Pragma no-cache;
}

5. 静态资源防盗链

防盗链就是防止别人盗用服务器中的图片、文件、视频等相关资源。防盗链:是通过location + rewrite + http_refer实现的。

1. 基于 http_refer 防盗链配置模块

1
2
3
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location

2. 准备html文件

1
2
3
4
5
6
7
8
9
<html>
<head>
<meta charset="utf-8">
<title>pachong<title>
</head>
<body style="background-color:red;">
<img src="http://192.168.69.113/test.jpg">
</body>
</html>

3. 启动防盗链

1
2
3
4
5
6
7
8
9
10
11
location ~* \.(wma|wmv|asf|mp3|mmf|zip|rar|gif|png|swf|flv|jpeg) {
valid_referers nonde blocked *.zhen.com zhen.com;
if ($invalid_referer) {
rewrite ^/ http://www.zhen.com/error.jpg;
}
}

#注意:不能存在以下缓存配置:
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
expires xxx;
}

4. 验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 伪造协议头访问
[root@C-Server ~]# curl -e "http://www.baidu.com" -I http://192.168.69.113/test.jpg
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Tue, 17 Apr 2018 04:55:18 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

// 伪造协议头访问
[root@C-Server ~]# curl -e "http://www.xuliangwei.com" -I http://192.168.69.113/tes
t.jpg
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 17 Apr 2018 04:55:27 GMT
Content-Type: image/jpeg
Content-Length: 174315
Last-Modified: Wed, 29 Nov 2017 03:16:08 GMT
Connection: keep-alive
ETag: "5a1e2678-2a8eb"
Expires: Tue, 17 Apr 2018 16:55:27 GMT
Cache-Control: max-age=43200
Accept-Ranges: bytes
-------------本文结束感谢您的阅读-------------