Nignx知识终结

[TOC]

nignx基本配置文件说明

nginx.conf配置结构

  • main 全局配置
  • event 配置工作模式和连接数
  • http http模块相关配置
    • server虚拟主机配置,可以配置多个
    • location 路由规则,表达式
    • upstream 集群,内网服务器

nginx.conf配置说明

nginx.conf默认所在位置/usr/local/nginx/conf/

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# user 指定运行 nginx 的用户和组(第一个参数为用户第二个为组,这里只有用户)
#user nobody;

# 指定工作进程数(一般设置为CPU核数)
worker_processes 1;

# 指定错误日志为 logs/ 目录下的 error.log 文件
#error_log logs/error.log;
# 日志格式有:debug,info,notice,warn,error,crit
# 指定错误日志,并指定写入格式为 notice
#error_log logs/error.log notice;
# 指定错误日志,并指定写入格式为 info
#error_log logs/error.log info;

# 指定 pid 文件(存放主进程 pid 号)
#pid logs/nginx.pid;

# nginx 连接配置模块
events {
# 默认使用epoll
use epoll
# 指定每个worker工作进程最大连接数为 1024
worker_connections 1024;
}

# http 配置模块
http {
# 通过 include 加载 mime.types 文件,里面的 types {} 模块将文件扩展名映射到响应的 MIME 类型
include mime.types;
# 定义响应的默认 MIME 类型
default_type application/octet-stream;

# 写入格式 main 的内容格式如下
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

# 指定访问日志和写入格式为 main
#access_log logs/access.log main;

# 启用或者禁用 sendfile()
sendfile on;
# 启用或者禁用使用套接字选项(仅在 sendfile 使用时使用)
#tcp_nopush on;

# 0 值禁用保持活动的客户端连接
#keepalive_timeout 0;
# 65 s 超时
keepalive_timeout 65;

# 启用或者禁用 gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,推荐1
gzip_comp_level 1;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml application/json application/xml+rss;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
# 设置压缩所需要的缓冲区大小
gzip_buffers 32 4k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;

# 虚拟主机配置模块
server {
# 监听 80 端口
listen 80;
# 监听域名为 localhost
server_name localhost;
# 将指定的 charset 添加到 “Content-Type” 响应头字段。如果此charset与source_charset指令中指定的charset不同,则执行转换。
#charset koi8-r;

# 指定该虚拟主机的访问日志
#access_log logs/host.access.log main;

# 将特定的文件或目录重新定位,如 php 文件,image 目录等
location / {
# 设置请求的根目录
root html;
# 定义索引,按顺序匹配
index index.html index.htm;
}

# 定义显示 404 错误的 uri
#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'
location = /50x.html {
root html;
}

location /image {
alias /home;
}
# 使用别名的方式加载,于上面的/image效果一致,作用避免暴露服务器文件目录结构
location /static {
alias /home/image;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
# 正则表达式匹配 php 文件
#location ~ \.php$ {
# 设置代理服务器的协议和地址,以及应该映射位置的可选URI。作为协议,可以指定“http”或“https”。该地址可以指定为一个域名或IP地址,以及一个可选端口
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# 设置 FastCGI 服务器的地址。地址可以指定为一个域名或 IP 地址,以及一个端口
# fastcgi_pass 127.0.0.1:9000;
# 设置将在以斜杠结尾的URI之后追加的文件名,
# fastcgi_index index.php;
# 设置一个应该传递给FastCGI服务器的参数。
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# 加载 conf/fastcgi_params 文件
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
# ssl 配置,要启用 ssl 模块需要在编译 nginx 时加上 --with-http_ssl_module 参数
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

nginx命令

命令 作用
nginx -s stop 停止nginx
nginx -s reload 重新加载配置
nginx -t 检测配置文件是否正确
nginx -V 查看nginx版本号和启动信息

nginx日志切割

  • 切割脚本

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash
    LOG_PATH="/var/log/nginx/"
    RECORD_TIME=$(date -d "yesterday" +%Y-%m-%d+%H:%M)
    PID=/var/run/nginx.pid
    mv ${LOG_PATH}/access.log ${LOG_PATH}/access.${RECORD_TIME}.log
    mv ${LOG_PATH}/error.log ${LOG_PATH}/error.${RECORD_TIME}.log
    #向Nginx主进程发送信号,用于重新打开日志文件
    kill -USR1 `cat $PID`

    pid文件可以使用nginx -V或者在nginx.conf中查看

location 正则匹配

语法规则: location [ = | ~ | ~ * | ^~ ] /uri/ { … }

1. = :精确匹配

1
2
3
4
5
6
7
8
# 精确匹配,必须是127.0.0.1/
location = / {
#规则A
}
# 精确匹配,必须是127.0.0.1/login
location = /login {
#规则B
}

2. ^~: 表示uri以某个常规字符串开头

可以理解为匹配 url路径即可

nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)

1
2
3
4
## 非精确匹配,并且不区分大小写,比如127.0.0.1/static/js.
location ^~ /static/ {
#规则C
}

3. ~:区分大小写的正则匹配

1
2
3
4
## 区分大小写,以gif,jpg,js结尾
location ~ \.(gif|jpg|png|js|css)$ {
#规则D
}

4. ~*:不区分大小写的正则匹配

1
2
3
4
## 不区分大小写,匹配.png和.PNG结尾的
location ~* \.png$ {
#规则E
}

5. !~!~* 分别为区分大小写不匹配不区分大小写不匹配 的正则

1
2
3
4
5
6
7
## 区分大小写,匹配不以.xhtml结尾的
location !~ \.xhtml$ {
#规则F
}
location !~* \.xhtml$ {
#规则G
}

6. / 通用匹配,任何请求都会匹配到

1
2
3
4
## 什么都可以
location / {
#规则H
}

7. 匹配顺序

多个location配置的情况下匹配顺序为:
首先匹配=
其次匹配^~
再其次是按文件中顺序的正则匹配;
最后是交给 / 通用匹配;
当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

匹配效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
访问根目录/, 比如http://localhost/    //将匹配规则A

访问 http://localhost/login 将匹配规则B

访问 http://localhost/register 则匹配规则H

访问 http://localhost/static/a.html 将匹配规则C

访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用, 而 http://localhost/static/c.png 则优先匹配到 规则C

访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。

访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。

访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。

8. 常用规则

  • 第一个规则

    1
    2
    3
    location = / {
    proxy_pass http://127.0.0.1:3000/
    }
  • 第二规则

    第二个规则是处理静态文件请求,这是nginx作为http服务器的强项
    有两种配置模式,目录匹配后缀匹配,任选其一或搭配使用

    1
    2
    3
    4
    5
    6
    7
    location ^~ /static/ {
    root /webroot/static/;
    }

    location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
    }
  • 第三规则

    用来转发动态请求到后端应用服务器

    1
    2
    3
      location /api/ {
    proxy_pass http://127.0.0.1:3000/api/
    }

nginx跨域支持

1
2
3
4
5
6
7
8
9
10
server{
#允许跨域请求的域,*代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
}

nginx防盗链

1
2
3
4
5
6
7
8
9
10
11
12
location ~* \.(gif|jpg|swf)$ { 
# 防盗链,指定*.caihc.site *.caihc.com这两个域名才可以访问
valid_referers *.caihc.site *.caihc.com;
if ($invalid_referer) {
# 重定向到logn文件
# rewrite ^/ http://$host/logo.png;

# 返回404状态
return 404;
}

}

说明:
如果 valid_referers 条件判断未通过,nginx 则会赋值 invalid_referertrue
语法: valid_referers none | blocked | server_names | string ...;

参数说明:
none: 不允许 “Referer” 来源头部为空的情况
blocked: 不允许“Referer”值为空情况,有可能Referer的值被代理或者防火墙删除
server_names: “Referer”来源头部包必须含当前的server_names (当前域名)可以多个

nginx负载均衡:upstream

官方文档地址:http://nginx.org/en/docs/http/ngx_http_upstream_module.html

轮询

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream tomcats {
server 192.168.1.173:8080;
server 192.168.1.174:8080;
server 192.168.1.175:8080;
}
server{
listen 80;
server_name tomcats.caihc.site;
location / {
# 指定使用的upstream
proxy_pass http://tomcats;
}
}

权重

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream tomcats {
server 192.168.1.173:8080 weight=1;
server 192.168.1.174:8080 weight=2;
server 192.168.1.175:8080 weight=3;
}
server{
listen 80;
server_name tomcats.caihc.site;
location / {
# 指定使用的upstream
proxy_pass http://tomcats;
}
}

weight权重越高处理的请求就越多

ip_hash

ip_hash 可以保证用户访问可以请求到上游服务中的固定的服务器,前提是用户ip没有发生更改。
使用ip_hash的注意点:
不能把后台服务器直接移除,只能标记 down .

If one of the servers needs to be temporarily removed, it should be marked with the down parameter in order to preserve the current hashing of client IP addresses.

1
2
3
4
5
6
upstream tomcats {
ip_hash;
server 192.168.1.173:8080;
server 192.168.1.174:8080 down;
server 192.168.1.175:8080;
}

upstream 参数

  • max_conns

    限制每台server的连接数,用于保护避免过载,可起到限流作用

    1
    2
    3
    4
    5
    upstream tomcats {
    server 192.168.1.173:8080 max_conns=2;
    server 192.168.1.174:8080 max_conns=2;
    server 192.168.1.175:8080 max_conns=2;
    }
  • slow_start

    商业版需要付费,在指定时间内缓慢加入集群

    1
    2
    3
    4
    5
    upstream tomcats {
    server 192.168.1.173:8080 weight=6 slow_start=60s;
    server 192.168.1.174:8080 weight=2;
    server 192.168.1.175:8080 weight=2;
    }

    注意

    1. 该参数不能使用在 hash 和 random load balancing 中。
    2. 如果在 upstream 中只有一台 server,则该参数失效。
  • down、backup

    down用于标记服务节点不可用:

    1
    2
    3
    4
    5
    upstream tomcats {
    server 192.168.1.173:8080 down;
    server 192.168.1.174:8080 weight=1;
    server 192.168.1.175:8080 weight=1;
    }

    backup表示当前服务器节点是备用机,只有在其他的服务器都宕机以后,自己才会加入到集群中,被用户访问到:

    1
    2
    3
    4
    5
    upstream tomcats {
    server 192.168.1.173:8080 backup;
    server 192.168.1.174:8080 weight=1;
    server 192.168.1.175:8080 weight=1;
    }

    注意

    1. backup 参数不能使用在 hash 和 random load balancing 中。
  • max_fails、fail_timeout

    max_fails :表示失败几次,则标记server已宕机,剔出上游服务。
    fail_timeout :表示失败的重试时间

    1
    2
    3
    4
    5
    upstream tomcats {
    server 192.168.1.173:8080 backup;
    server 192.168.1.174:8080 weight=1;
    server 192.168.1.175:8080 weight=1 max_fails=2 fail_timeout=15s;
    }

    则代表在15秒内请求某一server失败达到2次后,则认为该server已经挂了或者宕机了,随后再过15秒,这15秒内不会有新的请求到达刚刚挂掉的节点上,而是会
    运作的server,15秒后会再有新请求尝试连接挂掉的server,如果还是失败,重复上一过程,直到恢复。

使用Keepalived 提高吞吐量

keepalived : 设置长连接处理的数量
proxy_http_version :设置长连接http版本为1.1
proxy_set_header :清除connection header 信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream tomcats {
server 192.168.1.173:8080 max_fails=2 fail_timeout=1s;
server 192.168.1.190:8080;
keepalive 32;
}
server {
listen 80;
server_name www.tomcats.com;
location / {
proxy_pass http://tomcats;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}

nginx缓存

控制浏览器缓存

  • 浏览器缓存和nginx缓存的区别

    1. 浏览器缓存:
      加速用户访问,提升单个用户(浏览器访问者)体验,缓存在本地
    2. Nginx缓存
      缓存在nginx端,提升所有访问到nginx这一端的用户
      提升访问上游(upstream)服务器的速度
      用户访问仍然会产生请求流量
  • 使用expires控制缓存

    1
    2
    3
    4
    5
    6
    7
    8
    9
    location /static { # 用于静态文件缓存控制
    alias /home/caihc;
    # expires 10s; # 缓存过期时间为10秒
    # expires @22h30m; # 22点30分,缓存过期
    # expires -1h; # 缓存在1个小时前过期
    # expires epoch; # 不使用缓存(关闭nginx和浏览器端的缓存)
    # expires off; # 关闭nginx端的缓存
    expires max; # 缓存永不过期
    }

反向代理缓存

用于缓存服务端文件

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
upstream tomcats {
server 192.168.1.173:8080;
server 192.168.1.174:8080;
server 192.168.1.175:8080;
}

# proxy_cache_path 设置缓存目录
# keys_zone 设置共享内存以及占用空间大小
# max_size 设置缓存大小
# inactive 超过此时间则被清理
# use_temp_path 临时目录,使用后会影响nginx性能,建议关闭(off)
proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:5m max_size=1g inactive=1m use_temp_path=off;

server{
listen 80;
server_name tomcats.caihc.site;

# 启用缓存,和keys_zone一致
proxy_cache mycache;
# 针对200和304状态码缓存时间为8小时
proxy_cache_valid 200 304 8h;

location / {
# 指定使用的upstream
proxy_pass http://tomcats;
}
}

nginx使用https

注意: ssl 配置,要启用 ssl 模块需要在编译 nginx 时加上 –with-http_ssl_module 参数

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
upstream tomcats {
server 192.168.1.173:8080;
server 192.168.1.174:8080;
server 192.168.1.175:8080;
}


server{
listen 80;
server_name tomcats.caihc.site;
# 开启ssl
ssl on;
# 配置ssl证书
ssl_certificate 1_tomcats.caihc.site.crt;
# 配置证书秘钥
ssl_certificate_key 2_tomcats.caihc.site.key;
# ssl会话cache
ssl_session_cache shared:SSL:1m;
# ssl会话超时时间
ssl_session_timeout 5m;
# 配置加密套件,写法遵循 openssl 标准
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

location / {
# 指定使用的upstream
proxy_pass http://tomcats;
# 解决https的request.getScheme() return http but not https.
proxy_redirect http:// $scheme://;
}
}

nginx配置websocket

1
2
3
4
5
6
7
8
location / {
# websocket配置
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'Upgrade';
proxy_connect_timeout 60s; # 发起握手等候响应超时时间
proxy_read_timeout 60s; # 连接成功后_等候后端服务器响应时间
proxy_send_timeout 60s; # 后端服务器数据回传时间
}

nginx限流

IP限流

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
http {
# 根据IP地址限制速度
# 1) 第一个参数 $binary_remote_addr
# binary_目的是缩写内存占用,remote_addr表示通过IP地址来限流
# 2) 第二个参数 zone=iplimit:20m
# iplimit(自定义参数)是一块内存区域(记录访问频率信息),20m是指这块内存区域的大小
# 3) 第三个参数 rate=1r/s 每秒一次请求
# 比如100r/m,标识访问的限流频率
limit_req_zone $binary_remote_addr zone=iplimit:20m rate=1r/s;
server {
server_name chc.com;
location /ip-limit/ {
# 基于IP地址的限制
# 1) 第一个参数zone=iplimit => 引用limit_req_zone中的zone变量
# 2) 第二个参数burst=2,缓冲队列的长度。
# 请求数量超过限流频率时,将其放入缓冲区域
# 3) 第三个参数nodelay=> 缓冲区满了以后,直接返回503异常
limit_req zone=iplimit burst=2 nodelay;

# 异常情况,返回504(默认是503)
limit_req_status 504;
limit_conn_status 504;
}
}
}

服务器级别的限流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
http {
# 根据服务器限制速度
# 1) 第一个参数 $server_name
# server_name 服务器访问名称
# 2) 第二个参数 zone=serverlimit:20m
# serverlimit(自定义参数)是一块内存区域(记录访问频率信息),20m是指这块内存区域的大小
# 3) 第三个参数 rate=100r/s 每秒100次请求
# 比如100r/m,标识访问的限流频率
limit_req_zone $server_name zone=serverlimit:10m rate=100r/s;
server {
server_name chc.com;
location /server-limit/ {
# 基于服务器级别的限制
# 通常情况下,server级别的限流速率是最大的
# burst=2,缓冲队列的长度
# nodelay=> 缓冲区满了以后,直接返回503异常
limit_req zone=serverlimit burst=100 nodelay;

# 异常情况,返回504(默认是503)
limit_req_status 504;
limit_conn_status 504;
}
}
}

连接数级别的限流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
# 基于Ip连接数的配置
# perip(自定义参数)是一块内存区域(记录访问频率信息),20m是指这块内存区域的大小
limit_conn_zone $binary_remote_addr zone=perip:20m;
# 基于服务器连接数的配置
# perserver(自定义参数)是一块内存区域(记录访问频率信息),20m是指这块内存区域的大小
limit_conn_zone $server_name zone=perserver:20m;
server {
server_name chc.com;
location /conn-limit/ {
# 每个server最多保持100个连接
limit_conn perserver 100;
# 每个IP地址最多保持5个连接
limit_conn perip 5;

# 异常情况,返回504(默认是503)
limit_req_status 504;
limit_conn_status 504;
}
}
}