├── HTTP缓存与header模块.md
├── OpenSSL.md
├── README.md
├── https基本操作.md
├── limit连接限流.md
├── proxy代理.md
├── 命令行与热部署操作.md
├── 基本命令.md
├── 日志管理.md
└── 连接处理方法IO.md
/HTTP缓存与header模块.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [HTTP缓存](#HTTP缓存)
3 | * [缓存控制](#缓存控制)
4 | * [缓存校验](#缓存校验)
5 | * [200状态码](#200状态码)
6 | * [304状态码](#304状态码)
7 | * [200fromDiskCache](#200fromDiskCache)
8 | * [具体缓存流程](#具体缓存流程)
9 | * [header模块](#header模块)
10 | * [expires](#expires)
11 | * [add_header](#add_header)
12 | * [Yii2框架HTTP缓存源码](#Yii2框架HTTP缓存源码)
13 |
14 | # HTTP缓存
15 | ## 缓存控制
16 | HTTP缓存分为缓存控制和缓存校验,缓存控制有Cache-Control和Pragma
17 |
18 | Pragma是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段。如果一个报文中同时出现Pragma和Cache-Control时,以Pragma为准。同时出现Cache-Control和Expires时,以Cache-Control为准。即优先级从高到低是 Pragma -> Cache-Control -> Expires
19 |
20 | 如果在请求header有如下参数
21 | ```
22 | Cache-Control: public,max-age=86400
23 | Pragma: no-cache
24 | ```
25 | 则Pragma的优先级更高
26 |
27 | Cache-Control一般值为
28 | - no-cache,表示不管有没有缓存都去拿真实数据,不会发生304,就是强制刷新
29 | - max-age=0,表示不管响应怎么设置,在重新获取数据前需要去校验ETag或者Last-Modified,校验通过就是304,就是在页面正常刷新
30 | - max-age=自己设置的值,服务器响应客户端,表示要求客户端缓存多长时间
31 |
32 | ## 缓存校验
33 | 缓存校验有Last-Modified和ETag
34 |
35 | 如果请求Cache-Control值为max-age=0,表示客户端要去服务端做资源校验,校验通过会发生304,使用本地缓存的资源,校验不通过的话,服务端将数据返回给客户端
36 |
37 | 服务端在响应时候会有响应头Last-Modified,这是一个格林威治时间,表示资源最后的修改时间
38 | ```
39 | Last-Modified: Thu, 01 Aug 2019 07:24:42 GMT
40 | ```
41 | 客户端在刷新页面时候,会发一个请求头If-Modified-Since,表示收到的上一次服务端给的Last-Modified
42 | ```
43 | If-Modified-Since: Thu, 01 Aug 2019 07:24:42 GMT
44 | ```
45 | 当服务端会对比自己的Last-Modifed和客户端的If-Modified-Since,如果
46 |
47 | If-Modified-Since >= Last-Modifed
48 |
49 | 那么服务端会直接响应304,响应body体长度为0,以下为一个304响应的nginx-access日志
50 | ```
51 | 192.168.124.1 - - [31/Jul/2019:13:43:46 +0800] "GET /a.css HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, l
52 | ike Gecko) Chrome/73.0.3683.86 Safari/537.36"
53 | ```
54 | 但是Last-Modifed无法解决资源在一秒内连续修改的问题,一秒内连续修改后,客户端只会更新一次
55 |
56 | 更好的解决方法是ETag,服务器会响应一个根据资源算出来的字符,如
57 | ```
58 | ETag: "5d4293ba-19aa"
59 | ```
60 | 第二次客户端请求时候会携带If-None-Match请求头
61 | ```
62 | If-None-Match: "5d4293ba-19aa"
63 | ```
64 | 如果
65 |
66 | If-None-Match == ETag
67 |
68 | 表示资源没有修改,服务端响应304
69 |
70 | 如果同时有ETag和Last-Modify,则ETag的优先级会更高
71 |
72 | 但是ETag也有问题,如果服务端是多节点集群,那么有可能A节点算出来的ETag和B节点的ETag可能不同,造成无法正常304响应,在nginx中可以关闭ETag
73 | ```
74 | etag off;
75 | ```
76 | ## 200状态码
77 | 200状态码会发生于浏览器第一次加载页面、强制刷新、304校验失败、资源缓存过期、浏览器禁用缓存情况
78 |
79 | 如果是浏览器第一次加载,那么请求头不会有Cache-Control、If-None-Match、If-Modified-Since
80 |
81 | 服务端正常响应200,正常将数据传给客户端
82 |
83 | 如果是强制刷新,那么浏览器会强制加请求头
84 | ```
85 | Cache-Control: no-cache
86 | Pragma: no-cache
87 | ```
88 | 表示需要服务端响应真实数据,不用做校验
89 |
90 | 如果浏览器禁用了缓存Disable Cache,那么也会强制加请求头no-cache
91 | ## 304状态码
92 | 304状态码会发生于刷新页面情况
93 |
94 | 刷新情况浏览器会强制加请求头
95 | ```
96 | Cache-Control: max-age=0
97 | ```
98 |
99 | 表示需要浏览器校验,校验成功就是304,校验失败就是200
100 | ## 200fromDiskCache
101 | 发生过程
102 | - 浏览器输入url
103 | - 再开一个新窗口,输入url,发生200from disk cache
104 |
105 | 由于访问静态资源,服务端通常都会响应Cache-Control:max-age,表示需要客户端缓存这个静态资源多长时间,如
106 | ```
107 | Cache-Control: max-age=36536000
108 | ```
109 | 同一个浏览器新窗口再次访问会发生from disk cache
110 |
111 | from disk cache情况服务端不会收到请求
112 | ## 具体缓存流程
113 | - 浏览器第一次加载url,不会有请求头Cache-Control、If-None-Match、If-Modified-Since,服务端响应200,响应头为
114 | ```
115 | Cache-Control:max-age=86400 //告诉客户端缓存86400秒
116 | Last-Modify:Wed,31 Jul 2019 04:05:42 GMT //资源最后修改时间
117 | ETage: "asdadsa" //资源的ETag
118 | ```
119 | - 刷新页面(服务端资源未修改),请求头如下,发生304
120 | ```
121 | If-Modified-Since:Wed,31 Jul 2019 04:05:42 GMT //客户端保存的资源最后修改时间
122 | ETag: "asdadsa"
123 | ```
124 | - 刷新页面(服务端资源修改),发生200
125 | - 强制刷新,请求头,发生200
126 | ```
127 | Cache-Control:no-cache
128 | ```
129 | - 新打开一个页面,缓存86400秒内,发生200 from disk cache
130 | - 新打开一个页面,缓存86400秒外,发生200
131 |
132 | # header模块
133 | ## expires
134 | ```
135 | Syntax: expires [modified] time;
136 | expires epoch | max | off;
137 | Default:
138 | expires off;
139 | Context: http, server, location, if in location
140 | ```
141 | 响应码为200, 201, 206, 301, 302, 303, 307, 308情况下会发这个响应头
142 | 参数可以是正数或者负数,如果为负,则发送的头为
143 | ```
144 | Cache-Control:no-cache
145 | ```
146 | 可以配置max,这样响应的就是,可以认为是永久缓存
147 | ```
148 | Expires:Thu,31 Dec 2037 23:55:55 GMT
149 | Cache-Control:max-age=315360000
150 | ```
151 | off参数可以禁用添加或者修改expire和Cache-Control响应
152 |
153 | # add_header
154 | ```
155 | Syntax: add_header name value [always];
156 | Default: —
157 | Context: http, server, location, if in location
158 | ```
159 | 响应码为200、201、204、206、301、302、303、304、307、308则添加指定的响应头
160 | 如果当前级别没有add_header,则从上一个级别继承,仅仅当前级别没有的话
161 | 如果定义了always,则不管响应码为多少都添加header
162 |
163 |
--------------------------------------------------------------------------------
/OpenSSL.md:
--------------------------------------------------------------------------------
1 | **(未完成)**
2 |
3 | 联系作者
4 | - weixin: 363260961
5 | - QQ: 363260961
6 |
7 | **编写不易,转载请注明出处https://github.com/Zhucola/advanced-nginx**
8 |
9 | 使用版本
10 | - CentOS Linux release 7.5.1804 (Core)
11 | - nginx/1.12.2版本
12 | - curl 7.61.0 (x86_64-pc-linux-gnu) libcurl/7.61.0 OpenSSL/1.0.2k zlib/1.2.7
13 | - OpenSSL 1.0.2p 14 Aug 2018
14 | ## 目录
15 | * [随机数](#随机数)
16 | * [秘钥RSA](#秘钥RSA)
17 | * [查看RSA秘钥公私钥、结构](#查看RSA秘钥公私钥、结构)
18 | * [查看RSA秘钥是否被篡改](#查看RSA秘钥是否被篡改)
19 | * [秘钥DSA](#秘钥DSA)
20 | * [查看DSA秘钥公私钥、结构](#查看DSA秘钥公私钥、结构)
21 | # 随机数
22 | openssl rand ...
23 | - \-out file 指定随机数输出文件
24 | - \-rand file 指定随机数种子文件
25 | - \-base64 编码为base64
26 | - \-hex 编码为hex
27 | - num 随机数长度
28 | ```openssl
29 | openssl rand 30
30 | openssl rand -rand /root/.rnd 30
31 | ```
32 | 输出结果为二级制
33 | ```openssl
34 | openssl rand -hex 30
35 | openssl rand -base64 30
36 | ```
37 | 输出结果为不二级制
38 |
39 | # 秘钥RSA
40 | openssl genrsa用于生成RSA私钥,**不会生成公钥,因为公钥提取自私钥**
41 |
42 | openssl genrsa
43 | - \-out filename 将指定的秘钥保存至filenme文件,若未指定则为标准输出
44 | - numbites 秘钥长度,该项必须为命令行最后一项
45 | - \-des等 加密私钥的算法
46 | - \-passout args 加密私钥文件的密码
47 |
48 | 密码是可选项,但是强烈推荐使用密码。密码可以安全的存储、传输和备份受保护的秘钥。但是可能每次重启web服务器都需要重新输入密码。如果需要更加安全,建议投资硬件
49 | ```openssl
50 | openssl genrsa –aes128 –out a.key 2048
51 | openssl genrsa -des3 -out a.key -passout pass:1234 2048
52 | ```
53 | # 查看RSA秘钥公私钥、结构
54 | ```openssl
55 | openssl genrsa -des3 -out a.key -passout pass:1234 2048
56 | openssl rsa -text -in a.key # 查看结构
57 | openssl rsa -in a.key -pubout -out a_pub.key -passin pass:1234 #查看公钥
58 | openssl rsa -in a.key -out a_priv.key #查看未加密的私钥
59 | ```
60 | # 查看RSA秘钥是否被篡改
61 | ```openssl
62 | openssl genrsa -des3 -out a.key -passout pass:1234 2048
63 | openssl rsa -in a.key -check -passin pass:1234
64 | ```
65 | # 秘钥DSA
66 | DSA秘钥生成分为两步,1.生成DSA参数2.秘钥创建
67 | ```openssl
68 | openssl dsaparam -genkey 2048 | openssl dsa -out d.key -aes128
69 | ```
70 | # 查看DSA秘钥公私钥、结构
71 | ```openssl
72 | openssl dsaparam -genkey 2048 | openssl dsa -out d.key -aes128
73 | openssl dsa -text -in d.key # 查看结构
74 | openssl dsa -in d.key -pubout -out d_pub.key #查看公钥
75 | openssl dsa -in d.key -out d_prive.key #查看私钥
76 |
77 | ```
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 未完成
2 |
3 | ## 目录
4 | * [基本命令.md](https://github.com/Zhucola/advanced-nginx/blob/master/%E5%9F%BA%E6%9C%AC%E5%91%BD%E4%BB%A4.md)
5 | * [OpenSSL.md](https://github.com/Zhucola/advanced-nginx/blob/master/OpenSSL.md)
6 | * [https操作.md](https://github.com/Zhucola/advanced-nginx/blob/master/https%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C.md)
7 | * [连接处理方法IO.md](https://github.com/Zhucola/advanced-nginx/blob/master/连接处理方法IO.md)
8 | * [日志管理.md](https://github.com/Zhucola/advanced-nginx/blob/master/日志管理.md)
9 | * [命令行与热部署操作.md](https://github.com/Zhucola/advanced-nginx/blob/master/命令行与热部署操作.md)
10 | * [limit连接限流.md](https://github.com/Zhucola/advanced-nginx/blob/master/limit%E8%BF%9E%E6%8E%A5%E9%99%90%E6%B5%81.md)
11 |
--------------------------------------------------------------------------------
/https基本操作.md:
--------------------------------------------------------------------------------
1 | **查看OpenSSL的基本操作请移步至 OpenSSL.md**
2 |
3 | ngx_http_ssl_module模块使nginx能够支持https
4 |
5 | 该模块**不默认编译**,使用该模块需要--with-http_ssl_module
6 |
7 | 该模块需要OpenSSL库
8 |
9 | 为了减少服务器负载,建议配置
10 | ```nginx
11 | worker_processes auto;
12 | http {
13 | server {
14 | listen 443 ssl;
15 | keepalive_timeout 70;
16 |
17 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
18 | ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
19 | ssl_certificate /usr/local/nginx/conf/cert.pem;
20 | ssl_certificate_key /usr/local/nginx/conf/cert.key;
21 | ssl_session_cache shared:SSL:10m;
22 | ssl_session_timeout 10m;
23 | }
24 | ```
25 |
26 | ## 目录
27 | * [ssl](#ssl)
28 | * [ssl_buffer_size](#ssl_buffer_size)
29 | * [ssl_protocols](#ssl_protocols)
30 | * [ssl_certificate ](#ssl_certificate)
31 | * [ssl_certificate_key](#ssl_certificate_key)
32 | * [ssl_password_file](#ssl_password_file)
33 | * [ssl_verify_client](#ssl_verify_client)
34 | * [ssl_client_certificate](#ssl_client_certificate)
35 | * [ssl_session_cache](#ssl_session_cache)
36 | * [ssl_session_timeout](#ssl_session_timeout)
37 |
38 | # ssl
39 | ```nginx
40 | Syntax: ssl on | off;
41 | Default: ssl off;
42 | Context: http, server
43 | ```
44 | 该指令在1.15.0以上版本被淘汰,应该使用listen 443 ssl;这种配置来代替
45 |
46 | # ssl_buffer_size
47 | ```
48 | Syntax: ssl_buffer_size size;
49 | Default: ssl_buffer_size 16k;
50 | Context: http, server
51 | ```
52 | 定义发送数据buffer区域的大小
53 |
54 | 如果发送的数据较大,则使用默认的16k就好
55 |
56 | 如果发送的数据小,则使用4k
57 |
58 | # ssl_protocols
59 | ```nginx
60 | Syntax: ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
61 | Default: ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
62 | Context: http, server
63 | ```
64 | 指定支持的协议版本
65 |
66 | 如果客户端使用的协议版本大于服务端支持的,则报错SSL23_GET_SERVER_HELLO:unsupported protocol
67 |
68 |
69 | **TLSv1.1 TLSv1.2 仅仅在OpenSSL1.0.1以上版本才支持**
70 |
71 | **TLSv1.3仅仅在OpenSSL1.1.1版本才支持**
72 |
73 | # ssl_certificate
74 | ```nginx
75 | Syntax: ssl_certificate file;
76 | Default: —
77 | Context: http, server
78 | ```
79 | 给指定的主机提供PEM格式的证书
80 |
81 | 如果还需要提供中间证书,那么应该按照顺序先指定主证书,然后提供中间证书
82 |
83 | 从版本1.11.0开始,该指令可以指定多个不同类型的证书,如RSA和ECDSA
84 | ```nginx
85 | server {
86 | listen 443 ssl;
87 | server_name example.com;
88 |
89 | ssl_certificate example.com.rsa.crt;
90 | ssl_certificate_key example.com.rsa.key;
91 |
92 | ssl_certificate example.com.ecdsa.crt;
93 | ssl_certificate_key example.com.ecdsa.key;
94 | ...
95 | }
96 | ```
97 | # ssl_certificate_key
98 | ```
99 | Syntax: ssl_certificate_key file;
100 | Default: —
101 | Context: http, server
102 | ```
103 | 提供一个配置与ssl_certificate证书的秘钥
104 |
105 | 配置了秘钥后,每次重启都需要重新输入秘钥密码,除非使用指令ssl_password_file指定密码
106 |
107 | # ssl_password_file
108 | ```
109 | Syntax: ssl_password_file file;
110 | Default: —
111 | Context: http, server
112 | ```
113 | 在1.7.3版本中出现
114 |
115 | 提供一个与指定ssl_certificate_key秘钥文件的密码
116 |
117 | **如果不指定该指令,并且秘钥有密码,reload即使输入了正确的密码,reload也不会生效**
118 |
119 | 其中可以提供多个密码,每一行一个,在使用密码的时候轮流尝试密码
120 | ```nginx
121 | server {
122 | listen 443 ssl;
123 | server_name example.com;
124 |
125 | ssl_certificate example.com.rsa.crt;
126 | ssl_certificate_key example.com.rsa.key;
127 | ssl_password_file /tmp/openssl/pass;
128 | ...
129 | }
130 | ```
131 | # ssl_verify_client
132 |
133 | ```
134 | Syntax: ssl_verify_client on | off | optional | optional_no_ca;
135 | Default: ssl_verify_client off;
136 | Context: http, server
137 | ```
138 | 是否校验客户端证书,校验结果会保存在变量$ssl_client_verify中
139 |
140 | 参数optional会请求客户端证书,客户端提供了证书的时候校验,不提供不校验
141 |
142 | 参数optional_no_ca会请求客户端证书,但是客户端证书不需要被CA证书信任
143 |
144 | 该指令与ssl_client_certificate 配套使用,需要指定ssl_client_certificate 参数
145 |
146 | # ssl_client_certificate
147 | ```
148 | Syntax: ssl_client_certificate file;
149 | Default: —
150 | Context: http, server
151 | ```
152 | 指定一个受信与CA的证书,这个证书用来做客户端证书校验
153 |
154 | 指定的证书在请求的时候**会**响应给给客户端
155 |
156 | ```nginx
157 | server {
158 | listen 443 ssl;
159 | keepalive_timeout 70;
160 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
161 | ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
162 | ssl_certificate /tmp/openssl/nginx.crt;
163 | ssl_certificate_key /tmp/openssl/a.key;
164 | ssl_password_file /tmp/openssl/pass;
165 | ssl_verify_client on;
166 | ssl_client_certificate /etc/pki/CA/cacert.pem;
167 | location / {
168 | return 200 123;
169 | }
170 | }
171 | ```
172 |
173 | # ssl_trusted_certificate
174 | ```
175 | Syntax: ssl_trusted_certificate file;
176 | Default: —
177 | Context: http, server
178 | ```
179 | 指定一个受信与CA的证书,这个证书用来做客户端证书校验
180 |
181 | 指定的证书在请求的时候**不会**响应给给客户端
182 |
183 | ## ssl_session_cache
184 | ```
185 | Syntax: ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
186 | Default: ssl_session_cache none;
187 | Context: http, server
188 | ```
189 | 定义如何存储session
190 |
191 | 参数none
192 |
193 | nginx告诉客户端可以重用session,但是nginx不会存储session,实际上没有使用session
194 |
195 | 参数off
196 |
197 | nginx告诉客户端不可以重用session
198 |
199 | 参数builtin
200 |
201 | 在OpenSSL中构建的缓存;由一个工作进程实现功能。缓存大小在会话中指定。如果没有给出大小,则等于20480个会话。使用内置缓存可能导致内存碎片化。
202 |
203 | 参数shared
204 |
205 | 在所有工作进程之间共享的高速缓存。缓存大小以字节指定;一兆字节可以存储大约4000个会话。每个共享缓存应该具有任意的名称。同一名称的缓存可以在多个虚拟服务器中使用
206 | ```
207 | ssl_session_cache builtin:1000 shared:SSL:10m;
208 | ```
209 | builtin和shared可以同时指定,但是使用shared会更加高效
210 |
211 | ## ssl_session_timeout
212 | ```
213 | Syntax: ssl_session_timeout time;
214 | Default: ssl_session_timeout 5m;
215 | Context: http, server
216 | ```
217 | 提供一个给客户端重用session的时间
218 |
--------------------------------------------------------------------------------
/limit连接限流.md:
--------------------------------------------------------------------------------
1 | 对于一些服务器流量异常、负载过大,甚至是大流量的恶意攻击访问等,进行并发数的限制;该模块可以根据定义的键来限制每个键值的连接数,只有那些正在被处理的请求(这些请求的头信息已被完全读入)所在的连接才会被计数。
2 | ## 目录
3 | * [limit_conn_zone](#limit_conn_zone)
4 | * [limit_conn](#limit_conn)
5 | * [limit_conn_status](#limit_conn_status)
6 | * [limit_conn_log_level](#limit_conn_log_level)
7 | * [并发限制于error_page的结合使用](#并发限制于error_page的结合使用)
8 |
9 | ## limit_conn_zone
10 | ```
11 | Syntax: limit_conn_zone key zone=name:size;
12 | Default: —
13 | Context: http
14 | ```
15 | 设置一个共享区间,用于存储各种各样的key的连接状态
16 |
17 | 该命令和limit_zone命令一起配合使用
18 |
19 | size的大小最小为32k(32K),否则会报错
20 | ```
21 | nginx: [emerg] zone "zone=test:30k" is too small in /usr/local/nginx/conf/nginx.conf:8
22 | ```
23 |
24 | 参数key可以是文本、变量和他们的组合
25 | ```
26 | http{
27 | limit_conn_zone $remote_addr zone=test:10m;
28 | limit_conn_status 503;
29 | server {
30 | listen 80;
31 | root /tmp;
32 | location / {
33 | fastcgi_pass http://127.0.0.1:9000;
34 | include fastcgi.conf;
35 | limit_conn test 5;
36 | }
37 | }
38 | }
39 | ```
40 | 以上配置的意思就是定一个名字是test,大小为10m的共享区间,该共享区间用以记录将请求的头信息已被完全读入的请求,记录的键为$remote_addr
41 |
42 | 比如并发情况下:
43 | 1.请求$remote_addr为127.0.0.1,则test区间127.0.0.1的键自增请求数为1
44 | 2.请求$remote_addr为127.0.0.1,则test区间127.0.0.1的键自增请求数为2
45 | 3.请求$remote_addr为127.0.0.1,则test区间127.0.0.1的键自增请求数为3
46 | 4.请求$remote_addr为192.168.1.1,则test区间192.168.1.1的键自增请求数为1
47 |
48 | 当$remote_addr并发请求数达到命令limit_conn test 5;所指定的大小5时,第5个并发返回503 Service Temporarily Unavailable
49 |
50 | 可以创建5个xshell窗口,在/tmp目录下创建文件a.php,a.php中sleep(50);,也就是阻塞50秒
51 |
52 | 5个窗口的$remote_addr为127.0.0.1,模拟5个并发操作,在第6个并发创建的时候,会返回503
53 |
54 | ```
55 | http{
56 | limit_conn_zone $uri zone=test:10m;
57 | limit_conn_status 503;
58 | server {
59 | listen 80;
60 | root /tmp;
61 | location / {
62 | fastcgi_pass http://127.0.0.1:9000;
63 | include fastcgi.conf;
64 | limit_conn test 5;
65 | }
66 | }
67 | }
68 | ```
69 | 也可以同时限制$uri的并发数量为5
70 | 比如:
71 | 1.请求$uri为/a,则test区间/a的键自增请求数为1
72 | 2.请求$uri为/a,则test区间/a的键自增请求数为2
73 | 3.请求$uri为/a,则test区间/a的键自增请求数为3
74 | 4.请求$uri为/b,则test区间/b的键自增请求数为1
75 |
76 | ```
77 | http{
78 | limit_conn_zone $HTTP_AAA zone=test:10m;
79 | limit_conn_status 503;
80 | server {
81 | listen 80;
82 | root /tmp;
83 | location / {
84 | fastcgi_pass http://127.0.0.1:9000;
85 | include fastcgi.conf;
86 | limit_conn test 5;
87 | }
88 | }
89 | }
90 | ```
91 | 也可以指定在请求中带head头为AAA的并发数量
92 |
93 | ```
94 | curl 'http://127.0.0.1/a.php' -H 'AAA: 123'
95 | ```
96 |
97 | 也就是说,如果heade头AAA值为123,那么最多接受5个并发;如果有请求没有heade头AAA,那么没有并发限制
98 |
99 | **注意**
100 | 如果用IP作为键限制,则应该使用$binary_remote_addr替代$remote_addr,因为$remote_addr参数长度在7至15个字节,而$binary_remote_addr长度在IPV4下总是为4字节,在IPV6下总是为16字节
101 |
102 | 如果区域存储已用完,服务器将将错误返回给所有其他请求
103 |
104 | ## limit_conn
105 | ```
106 | Syntax: limit_conn zone number;
107 | Default: —
108 | Context: http, server, location
109 | ```
110 | 比较难描述,直接看例子
111 | ```
112 | http{
113 | limit_conn_zone $HTTP_AAA zone=test:10m;
114 | limit_conn_status 503;
115 | server {
116 | listen 80;
117 | root /tmp;
118 | location / {
119 | fastcgi_pass http://127.0.0.1:9000;
120 | include fastcgi.conf;
121 | limit_conn test 5;
122 | }
123 | }
124 | }
125 | ```
126 | 以上就是定义了一个并发限制,名字是test,共享内存大小为10m,限制的键是$HTTP_AAA(也就是header头的AAA)
127 | ```
128 | curl 'http://127.0.0.1/a.php' -H 'AAA: 123'
129 | ```
130 | 当并发数量$HTTP_AAA达到6时候,第6个请求会保存,返回响应码506
131 |
132 | 也可以在一个location里面配置多个limit_conn
133 | ```
134 | http{
135 | limit_conn_zone $HTTP_AAA zone=test_1:10m;
136 | limit_conn_zone $uri zone=test_2:10m;
137 | limit_conn_status 503;
138 | server {
139 | listen 80;
140 | root /tmp;
141 | location / {
142 | fastcgi_pass http://127.0.0.1:9000;
143 | include fastcgi.conf;
144 | limit_conn test_1 5;
145 | limit_conn test_2 10;
146 | }
147 | }
148 | }
149 | ```
150 |
151 | limit_conn如果当前级别没有指明,则从前一个级别继承
152 | ```
153 | http{
154 | limit_conn_zone $HTTP_AAA zone=test:10m;
155 | limit_conn_status 503;
156 | server {
157 | listen 80;
158 | root /tmp;
159 | limit_conn test 5;
160 | location / {
161 | fastcgi_pass http://127.0.0.1:9000;
162 | include fastcgi.conf;
163 | }
164 | }
165 | }
166 | ```
167 |
168 | 则被location /的匹配的请求,会使用limit_conn test 5;
169 | ## limit_conn_status
170 | ```
171 | Syntax: limit_conn_status code;
172 | Default: limit_conn_status 503;
173 | Context: http, server, location
174 | ```
175 | 设置状态代码以响应拒绝的请求返回
176 |
177 | 注意这个code值应该在400和599之间
178 |
179 | 503的响应码具体信息为
180 | ```
181 |
182 |
503 Service Temporarily Unavailable
183 |
184 | 503 Service Temporarily Unavailable
185 |
nginx/1.14.1
186 |
187 |
188 | ```
189 | ## limit_conn_log_level
190 | ```
191 | Syntax: limit_conn_log_level info | notice | warn | error;
192 | Default: limit_conn_log_level error;
193 | Context: http, server, location
194 | ```
195 | 设置在并发超限情况下,在error_log中的日志级别
196 |
197 | 默认情况下为error级别报错,日志描述为
198 | ```
199 | 2018/11/12 23:05:51 [error] 21012#0: *12 limiting connections by zone "test_2", client: 127.0.0.1, server: localhost, request: "GET /a.php HTTP/1.1", host: "127.0.0.1"
200 | ```
201 |
202 | ## 并发限制于error_page的结合使用
203 |
204 | 使用ngx_http_limit_conn_module模块来做并发限频,默认情况下会返回http code503
205 | ```
206 |
207 | 503 Service Temporarily Unavailable
208 |
209 | 503 Service Temporarily Unavailable
210 |
nginx/1.14.1
211 |
212 |
213 | ```
214 | 这种非程序员能看懂的提示语不是我们想要的,所以我们应该结合error_page(https://github.com/Zhucola/advanced-nginx/blob/master/ngx_http_core_module.md#error_page) 命令来与并发限频一起使用
215 |
216 | ```
217 | http {
218 | include mime.types;
219 | limit_conn_zone $uri$HTTP_id zone=test:32k;
220 | server {
221 | listen 80;
222 | server_name localhost;
223 | error_page 599 = /response;
224 | location / {
225 | limit_conn_status 599;
226 | limit_conn test 10;
227 | root /tmp;
228 | fastcgi_pass 127.0.0.1:9000;
229 | include fastcgi.conf;
230 | }
231 | location /response {
232 | default_type application/json;
233 | return 200 '{"code":1,"message":"请求超限"}';
234 | }
235 | }
236 | }
237 | ```
238 | 以上配置中,如果请求$uri$HTTP_id并发达到了11,则limit_conn_status会返回599响应码,又因为我们有error_page指令,所以被转到location /response,最后返回
239 | ```
240 | < HTTP/1.1 200 OK
241 | < Server: nginx/1.14.1
242 | < Date: Mon, 12 Nov 2018 14:56:30 GMT
243 | < Content-Type: application/json
244 | < Content-Length: 35
245 | < Connection: keep-alive
246 | <
247 | * Connection #0 to host 127.0.0.1 left intact
248 | {"code":1,"message":"请求超限"}
249 | ```
250 |
--------------------------------------------------------------------------------
/proxy代理.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [proxy_connect_timeout](#proxy_connect_timeout)
3 | * [proxy_method](#proxy_method)
4 | * [proxy_http_version](#proxy_http_version)
5 | * [proxy_pass_request_body](#proxy_pass_request_body)
6 | * [proxy_pass](#proxy_pass)
7 | * [proxy_set_header](#proxy_set_header)
8 | * [underscores_in_headers](#underscores_in_headers)
9 | * [获取代理模式下的真实用户ip](#获取代理模式下的真实用户ip)
10 |
11 | # proxy_connect_timeout
12 | ```
13 | Syntax: proxy_connect_timeout time;
14 | Default:
15 | proxy_connect_timeout 60s;
16 | Context: http, server, location
17 | ```
18 | 设置于代理服务器的连接超时时间,这个时间不能超过75秒
19 | # proxy_method
20 | ```
21 | Syntax: proxy_method method;
22 | Default: —
23 | Context: http, server, location
24 |
25 | ```
26 | 指定代理方法而不是使用客户端请求的方法
27 |
28 | 如果client c -> proxy server s1 -> server s2
29 |
30 | 使用get方式请求client,那么s2收到的请求方式是get
31 |
32 | 如果在proxy server s1指定
33 | ```
34 | proxy_method POST;
35 | ```
36 | 那么收到的请求方式就是POST
37 |
38 | # proxy_http_version
39 | ```
40 | Syntax: proxy_http_version 1.0 | 1.1;
41 | Default:
42 | proxy_http_version 1.0;
43 | Context: http, server, location
44 | ```
45 | 1.1版本推荐在keep alive下使用
46 |
47 | 需要在每一个被使用到的proxy都设置
48 | # proxy_pass_request_body
49 | ```
50 | Syntax: proxy_pass_request_body on | off;
51 | Default:
52 | proxy_pass_request_body on;
53 | Context: http, server, location
54 | ```
55 | 决定是否传送原始body给代理服务器
56 |
57 | 单独将proxy_pass_request_body off还是会将body传给server端,需要
58 | ```
59 | location /x-accel-redirect-here/ {
60 | proxy_method GET;
61 | proxy_pass_request_body off;
62 | proxy_set_header Content-Length "";
63 | proxy_pass ...
64 | }
65 | ```
66 | # proxy_pass
67 | ```
68 | Syntax: proxy_pass URL;
69 | Default: —
70 | Context: location, if in location, limit_except
71 | ```
72 | 设置一个代理协议和地址
73 |
74 | 协议可以是http或者https,地址可以带端口和uri
75 | ```
76 | server {
77 | listen 80;
78 | location / {
79 | proxy_pass http://127.0.0.1:81;
80 | }
81 | }
82 | server {
83 | listen 81;
84 | location / {
85 | return 200 $request_uri;
86 | }
87 | }
88 | ```
89 | 请求80端口uri为/abc,将会proxy_pass到81端口,输出/abc
90 |
91 | ```
92 | server {
93 | listen 80;
94 | location /abc {
95 | proxy_pass http://127.0.0.1:81/xy;
96 | }
97 | }
98 | server {
99 | listen 81;
100 | location / {
101 | return 200 $request_uri;
102 | }
103 | }
104 | ```
105 | 请求80端口uri为/abcd,将会proxy_pass到81端口,输出/xyd,就是实际请求的uri(/abcd),与location的/abc做差集,结果为d,将d拼上proxy_pass的uri(/xy),最后代理过去的uri为/abcd
106 | ```
107 | server {
108 | listen 80;
109 | location /abc {
110 | proxy_pass http://127.0.0.1:81;
111 | }
112 | }
113 | server {
114 | listen 81;
115 | location / {
116 | return 200 $request_uri;
117 | }
118 | }
119 | ```
120 | 请求80端口uri为/abcd,将会proxy_pass到81端口,输出/abcd,因为proxy_pass没有默认的uri,所以不做差集处理
121 |
122 | ```
123 | server {
124 | listen 80;
125 | location /abc {
126 | proxy_pass http://127.0.0.1:81/;
127 | }
128 | }
129 | server {
130 | listen 81;
131 | location / {
132 | return 200 $request_uri;
133 | }
134 | }
135 | ```
136 | 请求80端口uri为/abcd,将会proxy_pass到81端口,输出/,因为proxy_pass有默认的uri为/,所以做差集处理
137 |
138 | ```
139 | server {
140 | listen 80;
141 | location /xxx {
142 | rewrite ^/xxx /yyy break;
143 | proxy_pass http://127.0.0.1:81;
144 | }
145 | }
146 | server {
147 | listen 81;
148 | location / {
149 | return 200 $request_uri;
150 | }
151 | }
152 | ```
153 | 请求80端口uri为/xxx,将会proxy_pass到81端口,因为有rewrite并且是break,所以改变了uri,输出/yyy
154 |
155 | ```
156 | server {
157 | listen 80;
158 | location /a {
159 | proxy_pass http://127.0.0.1:81/oooooo;
160 | }
161 | }
162 | server {
163 | listen 81;
164 | location / {
165 | return 200 $request_uri;
166 | }
167 | }
168 | ```
169 | 请求80端口uri为/abc,将会proxy_pass到81端口,uri做差集,最后输出结果为/oooooobc
170 |
171 | # proxy_set_header
172 | ```
173 | Syntax: proxy_set_header field value;
174 | Default:
175 | proxy_set_header Host $proxy_host;
176 | proxy_set_header Connection close;
177 | Context: http, server, location
178 | ```
179 | 允许重新定义或者追加header头到proxy服务器,可以包含文本、变量和他们的组合
180 | 指令会继承于上一个级别,如果当前级别没有proxy_set_header被定义
181 | ```
182 | server {
183 | listen 80;
184 | proxy_set_header AA aa;
185 | location / {
186 | proxy_pass http://127.0.0.1:81;
187 | }
188 | }
189 | server {
190 | listen 81;
191 | location / {
192 | return 200 $HTTP_AA;
193 | }
194 | }
195 | ```
196 | 请求80端口uri为/,会输出aa,因为80的location /里面没有定义proxy_set_header,所以会继承上一个级别的proxy_set_header
197 | ```
198 | server {
199 | listen 80;
200 | proxy_set_header AA aa;
201 | location / {
202 | proxy_set_header BB bb;
203 | proxy_pass http://127.0.0.1:81;
204 | }
205 | }
206 | server {
207 | listen 81;
208 | location / {
209 | return 200 $HTTP_AA;
210 | }
211 | }
212 | ```
213 | 请求80端口uri为/,会输出空
214 | ```
215 | server {
216 | listen 80;
217 | location / {
218 | proxy_set_header BB bb;
219 | proxy_pass http://127.0.0.1:81;
220 | }
221 | }
222 | server {
223 | listen 81;
224 | location / {
225 | proxy_set_header BB xx;
226 | proxy_pass http://127.0.0.1:82;
227 | }
228 | }
229 | server {
230 | listen 82;
231 | location / {
232 | return 200 $HTTP_BB;
233 | }
234 | }
235 | ```
236 | 请求80端口uri为/,会输出xx,相当于81端口对head头BB做了重写
237 | ```
238 | server {
239 | listen 80;
240 | location / {
241 | proxy_set_header AA aa;
242 | proxy_pass http://127.0.0.1:81;
243 | }
244 | }
245 | server {
246 | listen 81;
247 | location / {
248 | proxy_set_header BB bb;
249 | proxy_pass http://127.0.0.1:82;
250 | }
251 | }
252 | server {
253 | listen 82;
254 | location / {
255 | return 200 $HTTP_AA;
256 | }
257 | }
258 | ```
259 | 请求80端口uri为/,可以获取到第一次proxy添加的header头,所以输出aa
260 | # underscores_in_headers
261 | ```
262 | Syntax: underscores_in_headers on | off;
263 | Default:
264 | underscores_in_headers off;
265 | Context: http, server
266 | ```
267 | 自定义的header头变量是否可以带下划线
268 | ```
269 | server {
270 | listen 81;
271 | underscores_in_headers off;
272 | location / {
273 | proxy_set_header aa $http_a_b;
274 | proxy_pass http://127.0.0.1:82;
275 | }
276 | }
277 | server {
278 | listen 82;
279 | location / {
280 | return 200 $HTTP_AA;
281 | }
282 | }
283 | ```
284 | ```
285 | curl 'http://127.0.0.1:81' -H 'a_b: 123'
286 | ```
287 | 请求将获取不到aa的header头,需要将underscores_in_headers改为on这样才能获取到$http_a_b
288 | ```
289 | server {
290 | listen 81;
291 | underscores_in_headers on;
292 | location / {
293 | proxy_set_header aa $http_a_b;
294 | proxy_pass http://127.0.0.1:82;
295 | }
296 | }
297 | server {
298 | listen 82;
299 | location / {
300 | return 200 $HTTP_AA;
301 | }
302 | }
303 | ```
304 | ```
305 | curl 'http://127.0.0.1:81' -H 'a_b: 123'
306 | ```
307 | 输出123
308 |
309 | ```
310 | server {
311 | listen 81;
312 | underscores_in_headers on;
313 | location / {
314 | return 200 $HTTP_AA_A;
315 | }
316 | }
317 | ```
318 | ```
319 | curl 'http://127.0.0.1' -H 'AA_A: 123'
320 | ```
321 | 输出123
322 | ```
323 | server {
324 | listen 81;
325 | underscores_in_headers off;
326 | location / {
327 | return 200 $HTTP_AA_A;
328 | }
329 | }
330 | ```
331 | ```
332 | curl 'http://127.0.0.1' -H 'AA-A: 123'
333 | ```
334 | 输出123
335 | # 获取代理模式下的真实用户ip
336 | - Client C -> Server S S获取的remote_addr为C的ip
337 | - Client C1 -> proxy Server S1 -> proxy Server S2 -> Server S3 S3获取的remote_addr为S2的
338 |
339 | 在proxy_pass情况下,应该添加
340 | ```
341 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
342 | ```
343 | 这样Server S3获取的HTTP_X_FORWARDED_FOR为Client C1,Server S1 S3获取的remote_addr为S2的,真实的客户端ip为HTTP_X_FORWARDED_FOR最左端的
344 |
345 | 也可以在proxy Server S1中添加
346 | ```
347 | proxy_set_header X-Real-IP $remote_addr;
348 | ```
349 |
350 | 这样在Server S3中获取到的HTTP_X_REAL_IP就是client的ip
351 |
352 | Client C1 -> proxy Server S1 -> proxy Server S2 -> Server S3需要在每一个proxy里面都写proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,如果proxy Server S2中没写,则Server S3获取到的就是client c1,remote_addr为s1的
353 |
--------------------------------------------------------------------------------
/命令行与热部署操作.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [启动](#启动)
3 | * [停止](#停止)
4 | nginx -s stop
5 | * [优雅停止](#优雅停止)
6 | nginx -s quit
7 | * [平滑重启](#平滑重启)
8 | nginx -s reload
9 | * [指定配置文件操作](#指定配置文件操作)
10 | nginx -c /tmp/nginx.conf
11 | * [重新开始记录日志](#重新开始记录日志)
12 | nginx -s reopen
13 | * [检测语法错误](#检测语法错误)
14 | nginx -t
15 | * [查看版本信息和编译配置](#查看版本信息和编译配置)
16 | nginx -v
17 | * [热部署](#热部署)
18 |
19 | 默认编译后,nginx的可执行二进制文件在/usr/local/nginx/sbin目录下,可执行文件为nginx
20 |
21 | 我们需要执行
22 | ```
23 | cp /usr/local/nginx/sbin/nginx /usr/bin
24 | ```
25 |
26 | 这样才可以在全局中直接找到nginx的二进制文件
27 |
28 | # 启动
29 |
30 | 直接执行nginx
31 |
32 | 如果服务器已经有nginx在执行,再次执行nginx会报错
33 | ```
34 | nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
35 | ```
36 | # 停止
37 | ```
38 | nginx -s stop
39 | ```
40 | # 优雅停止
41 | ```
42 | nginx -s quit
43 | ```
44 |
45 | 优雅停止与停止的区别就是:
46 |
47 | -停止会直接停掉正在连接着的tcp请求,nginx会发送一个RST包,强行断开连接
48 |
49 | -优雅停止会让正在连接的tcp请求处理完,然后再进行停止;但是再连接过来的请求会失败
50 |
51 | # 平滑重启
52 | ```
53 | nginx -s reload
54 | ```
55 |
56 | # 指定配置文件操作
57 | nginx默认使用的配置文件在conf/nginx.conf中,如果我们需要使用其他路径的配置文件,进行指定配置文件操作
58 | ```
59 | nginx -c /tmp/nginx.conf
60 | ```
61 |
62 | # 重新开始记录日志
63 | ```
64 | nginx -s reopen
65 | ```
66 | 其实这个命令就是
67 | ```
68 | kill -USR1 nginx.pid # nginx.pid为nginx的master进程ID
69 | ```
70 |
71 | 有时需求为将nginx的access和error日志按小时切割
72 |
73 | 如果access和error日志位置在/tmp目录下
74 |
75 | ```
76 | 1. mv /tmp/nginx_access.log mv /tmp/nginx_access.log.2018.11.07.11
77 | 2. mv /tmp/nginx_error.log mv /tmp/nginx_error.log.2018.11.07.11
78 | 3.nginx -s reopen
79 | ```
80 | 执行后,将会在/tmp目录下面再次创建/tmp/nginx_access.log和/tmp/nginx_error.log日志文件
81 |
82 | ## 检测语法错误
83 | ```
84 | nginx -t
85 | nginx -T
86 | ```
87 | 这两个命令都可以检测配置文件是否有语法错误
88 |
89 | 一般为先检测语法错误,然后在启动或者重启nginx
90 |
91 | t与T的区别就是,T会显示详细的错误信息
92 |
93 | ## 查看版本信息和编译配置
94 | ```
95 | nginx -v
96 | nginx -V
97 | ```
98 | -v可以显示nginx的版本信息
99 |
100 | -V不光可以显示版本信息,还可以显示编译时候的配置、使用的编译gcc版本、OpenSSL信息
101 | ```
102 | [root@localhost conf]# nginx -V
103 | nginx version: nginx/1.12.2
104 | built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
105 | built with OpenSSL 1.0.2k-fips 26 Jan 2017
106 | TLS SNI support enabled
107 | configure arguments: --with-http_ssl_module --with-select_module --with-debug
108 | ```
109 |
110 | ## 热部署
111 | 如果需要升级nginx或者更改编译配置,不需要kill掉nginx的master进程,这样会断开正在连接中的tcp请求,造成短时间内服务器不可用
112 |
113 | 热部署就是在nginx运行期间升级nginx或者更改编译配置,使请求平滑过渡到新的nginx上
114 |
115 | 1.首先我们编译一个nginx,并且运行这个nginx
116 | ```
117 | cd nginx-1.12.2
118 | ./configure --prefix=/usr/local/nginx && make && make install
119 | /usr/local/nginx/sbin/nginx
120 | ```
121 | 2.为了模拟热部署操作,我们更改编译配置,再编译一个新的nginx,注意编译后的predix目录为/usr/local/new_nginx
122 | ```
123 | cd nginx-1.12.2
124 | ./configure --prefix=/usr/local/new_nginx --with-debug && make && make install
125 | ```
126 | 3.先查看nginx的进程状态,这个运行的nginx是我们第一次编译的nginx,master进程运行PID为28587
127 | ```
128 | [root@localhost sbin]# ps -ef | grep nginx
129 | root 28587 1 0 14:45 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
130 | nobody 28588 28587 0 14:45 ? 00:00:00 nginx: worker process
131 | ```
132 | 4.进行可执行nginx文件(/usr/local/nginx/sbin/nginx)操作
133 | ```
134 | mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
135 | cp /usr/local/new_nginx/sbin/nginx /usr/local/nginx/sbin
136 | ```
137 |
138 | 5.给正在运行的nginx发送USR2信号
139 | ```
140 | kill -USR2 28587
141 | ```
142 |
143 | 6.查看nginx的进程状态,可见有两个master进程了,28587是老的nginx的master进程PID,30186是新的nginx的master进程PID,这时新的连接会进入到新的nginx
144 | ```
145 | [root@localhost sbin]# ps aux | grep nginx
146 | root 28587 0.0 0.0 20536 796 ? Ss 14:45 0:00 nginx: master process /usr/local/nginx/sbin/nginx
147 | nobody 28588 0.0 0.1 20980 1056 ? S 14:45 0:00 nginx: worker process
148 | root 30186 0.0 0.1 20592 1580 ? S 14:58 0:00 nginx: master process /usr/local/nginx/sbin/nginx
149 | nobody 30187 0.0 0.1 21036 1072 ? S 14:58 0:00 nginx: worker process
150 | ```
151 | 7.给老的nginx发送WINCH信号
152 | ```
153 | kill -WINCH 28587
154 | ```
155 | 8.查看nginx进程信息,老nginx的worker进程已经不存在,老nginx的master还存在的目的是为了热部署回滚用
156 | ```
157 | [root@localhost sbin]# ps aux | grep nginx
158 | root 28587 0.0 0.0 20536 796 ? Ss 14:45 0:00 nginx: master process /usr/local/nginx/sbin/nginx
159 | root 30186 0.0 0.1 20728 1708 ? S 14:58 0:00 nginx: master process /usr/local/nginx/sbin/nginx
160 | nobody 30196 0.0 0.1 21152 1700 ? S 15:00 0:00 nginx: worker process
161 | ```
162 |
163 | **注意**
164 | **注意**
165 | **注意**
166 |
167 | 热部署有几个需要非常注意的几点:
168 |
169 | -在进程kill -USR2 操作后,所有的请求都会被新的nginx处理,即使将新的nginx的可执行文件移动到老版本的sbin目录下,但是新的nginx的各种配置还是使用新nginx的目录的nginx.conf,如以上的热部署操作,新请求使用的nginx.conf为/usr/local/new_nginx/conf/nginx.conf;所以在kill -USR2操作前,需要使用老版本的nginx.conf覆盖掉新版本的nginx.conf,如果nginx.conf里面还有include操作,也要复制include的文件到新版本中
170 |
171 | -操作kill -USR2需要找到可执行文件的位置,在查看nginx进程信息的时候会发现"nginx: master process /usr/local/nginx/sbin/nginx",也就是说需要在"/usr/local/nginx/sbin"进行可执行文件的剪切和复制操作,如果启动的时候将nginx可执行文件放到/usr/bin目录下,并且直接使用/usr/bin/nginx来启动,则需要执行
172 | ```
173 | mv /usr/bin/nginx /usr/bin/nginx.old
174 | cp /usr/local/new_nginx/sbin/nginx /usr/bin/nginx
175 | ```
176 |
--------------------------------------------------------------------------------
/基本命令.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [nginx如何处理一个请求](#nginx如何处理一个请求)
3 | * [ngx_http_core_module](#ngx_http_core_module)
4 | * [http](#http)
5 | * [default_type](#default_type)
6 | * [types](#types)
7 | * [root](#root)
8 | * [alias](#alias)
9 | * [error_page](#error_page)
10 | * [try_files](#try_files)
11 | * [merge_slashes](#merge_slashes)
12 | * [location](#location)
13 | * [server_tokens](#server_tokens)
14 | * [client_max_body_size](#client_max_body_size)
15 | * [client_header_timeout](#client_header_timeout)
16 | * [etag](#etag)
17 | * [return](#return)
18 | * [connection_pool_size](#connection_pool_size)
19 | * [interal](#interal)
20 | # nginx如何处理一个请求
21 |
22 | nginx首先选定由那一个虚拟主机来处理请求
23 | ```nginx
24 | server {
25 | listen 80;
26 | server_name a.com b.com;
27 | location / {
28 | return 200 "server_name is a.com b.com";
29 | }
30 | }
31 | server {
32 | listen 80;
33 | server_name c.com d.com;
34 | location / {
35 | return 500 "server_name is c.com d.com";
36 | }
37 | }
38 | ```
39 | 在这个配置中,nginx**仅仅**检查请求的host头以决定该请求由那个虚拟主机来处理,如果host头没有匹配任意一个虚拟主机,或者请求中根本没有包含host头,那nginx会将请求分发到定义在此端口上的默认虚拟主机,第一个被列出的虚拟主机就是nginx的默认虚拟主机。也可以显式的某个虚拟主机为默认虚拟主机(default_server从0.8.21开始使用,在以前版本使用default代替)
40 | ```curl
41 | curl 'http://127.0.0.1' -H 'host: a.com'
42 | ```
43 | 以上请求的host被指定为a.com,所以匹配到server_name a.com b.com,返回http_code 200,消息体server_name is a.com b.com
44 | ```curl
45 | curl 'http://127.0.0.1' -H 'host: c.com'
46 | ```
47 | 以上请求的host被指定为c.com,所以匹配到server_name c.com d.com,返回http_code 500,消息体server_name is c.com d.com
48 | ```curl
49 | curl 'http://127.0.0.1' -H 'host: xxx.com'
50 | ```
51 | 以上请求的host被指定为xxx.com,没有server_name与其匹配,所以nginx会将请求分发到定义在此端口上的默认虚拟主机(第一个被列出的),返回http_code 200,消息体server_name is a.com b.com
52 |
53 | 如果将nginx配置改为
54 | ```nginx
55 | server {
56 | listen 80;
57 | server_name a.com b.com;
58 | location / {
59 | return 200 "server_name is a.com b.com";
60 | }
61 | }
62 | server {
63 | listen 80 default_server;
64 | server_name c.com d.com;
65 | location / {
66 | return 500 "server_name is c.com d.com";
67 | }
68 | }
69 | ```
70 | ```curl
71 | curl 'http://127.0.0.1' -H 'host: xxx.com'
72 | ```
73 | 以上请求的host被指定为xxx.com,没有server_name与其匹配,所以nginx会将请求分发到定义在此端口上的默认虚拟主机(default_server定义的),返回http_code 500,消息体server_name is c.com d.com
74 | ```nginx
75 | server {
76 | listen 80;
77 | server_name "";
78 | return 444;
79 | }
80 | server {
81 | listen 80;
82 | server_name c.com d.com;
83 | location / {
84 | return 500 "server_name is c.com d.com";
85 | }
86 | }
87 | ```
88 | 设置主机名为空字符串以匹配未定义Host头的请求,而且返回了一个nginx特有的,非http标准码444,可以用来关闭连接
89 | ```curl
90 | curl 'http://127.0.0.1' -H 'host: xxx.com'
91 | ```
92 | 返回curl: (52) Empty reply from server
93 |
94 | 不是一定要返回444,可以根据自身的业务需求来处理逻辑,比如我要返回"没有host头与之匹配"
95 | ```nginx
96 | server {
97 | listen 80;
98 | server_name "";
99 | return 200 "没有host头与之匹配";
100 | }
101 | server {
102 | listen 80;
103 | server_name c.com d.com;
104 | location / {
105 | return 500 "server_name is c.com d.com";
106 | }
107 | }
108 | ```
109 | 从0.8.48版本开始,server_name "" 以成为主机名的默认设置,所以可以省略server_name ""
110 | ```nginx
111 | server {
112 | listen 192.168.1.111:80;
113 | server_name a.com;
114 | ...
115 | }
116 | server {
117 | listen 192.168.1.112:80;
118 | server_name b.com;
119 | ...
120 | }
121 | ```
122 | 上面的配置中,nginx首先检查请求的IP地址和端口是否匹配某个server块中的listen指令配置。接着nginx继续测试请求host头是否匹配这个server块中的某个server_name值,如果没有匹配则将这个请求交给默认主机。
123 |
124 | **默认服务器是监听端口的属性,所以不同的监听端口可以设置不同的默认服务器**
125 |
126 | # ngx_http_core_module
127 | ## http
128 | ```
129 | Syntax: http { ... }
130 | Default: —
131 | Context: main
132 | ```
133 | 为服务器提供配置文件上下文
134 |
135 | 如一个简单的配置示例
136 | ```
137 | http{
138 | include mime.types;
139 | server {
140 | listen 80;
141 | root /tmp;
142 | location / {
143 | return 200 "test";
144 | }
145 | }
146 | }
147 | ```
148 | ## default_type
149 | ```
150 | Syntax: default_type mime-type;
151 | Default: default_type text/plain;
152 | Context: http, server, location
153 | ```
154 | 该指令应该和types指令配合学习
155 |
156 | 定义**默认**响应类型(Content-Type),**默认**的意思就是文件的扩展名不在nginx定义的MIME映射表里
157 |
158 | 例外:如请求一个*.php文件,php扩展名不在MIME映射表,不会走default_type,因为php主动响应了Content-Type
159 |
160 | ```nginx
161 | root /tmp;
162 | index a.html;
163 | default_type text/plain;
164 | location / {
165 | return 200 123;
166 | }
167 | ```
168 | ```
169 | curl -v 'http://127.0.0.1'
170 | ```
171 | 以上会输出服务器响应结果,可见响应Content-Type: text/plain
172 | ```nginx
173 | root /tmp;
174 | index a.html;
175 | default_type a/b;
176 | location / {
177 | return 200 123;
178 | }
179 | ```
180 | ```
181 | curl -v 'http://127.0.0.1'
182 | ```
183 | 以上会输出服务器响应结果,可见响应Content-Type: a/b
184 | ```nginx
185 | root /tmp;
186 | index a.html;
187 | default_type a/b;
188 | location / {
189 | # 这里什么都不写
190 | }
191 | ```
192 | ```
193 | curl -v 'http://127.0.0.1'
194 | ```
195 | 执行命令echo "file is a.html" > /tmp/a.html,请求后响应Content-Type: text/html,不会执行default_type命令,因为会查看a.html,文件后缀html与imme.types里面的text/html html htm shtml;相匹配
196 |
197 | ## types
198 | ```
199 | Syntax: types { ... }
200 | Default: types {
201 | text/html html;
202 | image/gif gif;
203 | image/jpeg jpg;
204 | }
205 | Context: http, server, location
206 | ```
207 | 设置文件扩展名和响应的MIME类型的映射表,可以将多个扩展名映射到同一种类型
208 |
209 | nginx都会有一行include mime.types;的,可以去mime.types里面查看映射信息,里面包含了足够多的类型
210 |
211 | 如果不想使用mime.types,而为所有请求都响应唯一的Content-Type,可以使用如下配置
212 | ```nginx
213 | location / {
214 | types {}
215 | default_type application/json;
216 | }
217 | ```
218 |
219 | ## root
220 | ```
221 | Syntax: root path;
222 | Default:
223 | root html;
224 | Context: http, server, location, if in location
225 | ```
226 | 仅仅是将uri拼到root值的后面
227 |
228 | path值可以是变量,但是不能是$document_root和$realpath_root;因为$document_root和$realpath_root是根据root或者alias来定义的
229 |
230 | 如果nginx的编译路径是/usr/local/nginx,则默认的寻找的文件目录位置是/usr/local/nginx/html(因为root默认值是html)
231 | ```nginx
232 | root /tmp;
233 | location /a {
234 | return 200 $request_filename;
235 | }
236 | ```
237 | ```curl
238 | curl 'http://127.0.0.1/a/b'
239 | ```
240 | 会输出/tmp/a/b
241 |
242 | 如果想要输出根目录
243 | ```nginx
244 | root /tmp;
245 | location /a {
246 | return 200 $document_root;
247 | }
248 | ```
249 | 会输出/tmp
250 |
251 | 如果想要输出请求文件的真实目录
252 | ```nginx
253 | root /tmp;
254 | location /a {
255 | return 200 $request_filename;
256 | }
257 | ```
258 |
259 | ## alias
260 | ```
261 | Syntax: alias path;
262 | Default: —
263 | Context: location
264 | ```
265 | path值可以是变量,但是不能是$document_root和$realpath_root;因为$document_root和$realpath_root是根据root或者alias来定义的
266 |
267 | 指定一个指定路径的替换路径
268 |
269 | alias和rewrite不能同时出现
270 | ```nginx
271 | location /a {
272 | alias /tmp;
273 | return 200 $request_filename;
274 | }
275 | ```
276 | ```curl
277 | curl 'http://127.0.0.1/a/b'
278 | ```
279 | 会输出/tmp/b
280 | ```nginx
281 | merge_slashes on;
282 | location /a/ {
283 | alias /tmp;
284 | return 200 $request_filename;
285 | }
286 | ```
287 | ```curl
288 | curl 'http://127.0.0.1/a/b'
289 | ```
290 | 会输出/tmpb
291 | ```nginx
292 | location / {
293 | alias /tmp;
294 | return 200 $request_filename;
295 | }
296 | ```
297 | ```curl
298 | curl 'http://127.0.0.1/a/b'
299 | ```
300 | 会输出/tmp/a/b
301 | ```nginx
302 | root /tmp
303 | location /a {
304 | alias /tmp;
305 | return 200 $request_filename;
306 | }
307 | location /x {
308 | return 200 $request_filename;
309 | }
310 | ```
311 | ```curl
312 | curl 'http://127.0.0.1/x/y'
313 | ```
314 | 会输出/tmp/x/y
315 |
316 | ```curl
317 | curl 'http://127.0.0.1/a/b
318 | ```
319 | 会输出/tmp/b
320 | ## error_page
321 | ```
322 | Syntax: error_page code ... [=[response]] uri;
323 | Default: —
324 | Context: http, server, location, if in location
325 | ```
326 | 为错误定义显示的URI或者状态码
327 | 如果是fastcgi的服务器,则需要设置fastcgi的配置fastcgi_intercept_errors on;
328 | ```nginx
329 | root /tmp;
330 | error_page 404 /b;
331 | location / {
332 | return 404 /ii;
333 | }
334 | location /b {
335 | return 404 123;
336 | }
337 | ```
338 | 请求uri为/,会被location /匹配,返回404到error_page,error_page将uri变成/b重新查找location,找到location /b返回123,不会造成死循环
339 | ```nginx
340 | root /tmp;
341 | location /a {
342 | error_page 404 /b;
343 | }
344 | location /b {
345 | return 200 123;
346 | }
347 | ```
348 | 如果请求uri为/a,出现404,则uri变为/b,重新查找location,返回123;对于http_code,即使return 200,最后的结果也是404
349 | ```nginx
350 | root /tmp;
351 | location /a {
352 | error_page 404 /b;
353 | }
354 | ```
355 | 如果请求uri为/a,出现404,则uri变为/b,查找/tmp/b,返回/tmp/b的文件内容;对于http_code,即使return 200,最后的结果也是404
356 |
357 | ```nginx
358 | location / {
359 | error_page 500 502 503 504 /50x.html;
360 | }
361 | ```
362 | 对于http_code500 502 503 504,使用error_page
363 |
364 | ```nginx
365 | location /a {
366 | error_page 404 =200 /200.html;
367 | }
368 | ```
369 |
370 | 如果发生404,则error_page执行后的响应码是200,**注意404后面有一个空格**
371 |
372 | ```nginx
373 | location /a {
374 | error_page 404 = /200.php;
375 | }
376 | ```
377 | 如果URI将被发送到一个被代理的服务器处理,或者发送到一个FastCGI服务器处理,这些后端服务器又返回了不同的响应码,那么这些响应码可以由根据被处理后的结果展现,以上配置的最终响应码取决于/200.php,**注意等号两面都有空格**
378 | ```nginx
379 | error_page 404 =200 /b;
380 | location /a {
381 | return 404 123;
382 | }
383 | location /b {
384 | #找不到页面
385 | }
386 | ```
387 | 请求uri为/a,会被error_page请求到location /b,即使404 =200最后也会返回404,因为页面找不到
388 |
389 | ```nginx
390 | location /a {
391 | error_page 404 http://127.0.0.1:81/a;
392 | }
393 | location /b {
394 | error_page 404 =200 http://127.0.0.1:81/b;
395 | }
396 | ```
397 | 也可以进行重定向
398 | ```nginx
399 | location /a {
400 | error_page 404 @back;
401 | }
402 | location @back {
403 | return 200 $uri;
404 | }
405 | ```
406 | 如果不希望error_page改变uri,可以将错误转到一个命名路径,比如uri /a发生404,则跳转到location @back,最后返回/a,uri不会改变
407 |
408 | **如果不存在location @back,则会发生500 Internal Server Error**
409 |
410 | ## try_files
411 | ```
412 | Syntax: try_files file ... uri;
413 | try_files file ... =code;
414 | Default: —
415 | Context: server, location
416 | ```
417 | 按照指定顺序检查文件是否存在,并且使用第一个找到的文件来处理请求。文件路径是根据root和alias指令,将file参数拼接而成
418 |
419 | 如果找不到,则按最后一个参数指定的uri进行内部跳转
420 | ```
421 | server{
422 | root /tmp;
423 | index index.html;
424 | location / {
425 | try_files "/a" "/b";
426 | }
427 | }
428 | ```
429 | ```
430 | curl 'http://127.0.0.1'
431 | ```
432 | 创建echo "123" > a,uri为"/",try_files会找/tmp/a,这个文件,返回文件内容123
433 |
434 | 如果/tmp/a文件不存在,则会将请求uri变成/b,重新查找location,以上配置会返回http_code500,因为进入查找死循环
435 |
436 | 不能将"/a"改为"a",这样会查找/tmpa文件,也不能将"/b"改为"b",这样会将uri变成"b",正确的uri应该是"/b"
437 |
438 | try_files指令的优先级是大于index指令的
439 | ```
440 | server{
441 | root /tmp;
442 | index index.html;
443 | location / {
444 | try_files "/a" "/b";
445 | }
446 | location /b{
447 | return 200 "location b";
448 | }
449 | }
450 | ```
451 | 如果存在/tmp/index.html,请求uri为"/",不会查找/tmp/index.html,会直接找/tmp/a,找不到在继续找location /b
452 | ```
453 | server{
454 | root /tmp;
455 | index index.html;
456 | location / {
457 | try_files "/a" "/b" "/c" "/d";
458 | }
459 | }
460 | ```
461 | 以上配置,会查找/tmp/a、/tmp/b、/tmp/c文件,如果有一个找到则停止查找;如果都找不到则uri变成/d
462 |
463 | ```
464 | server{
465 | root /tmp;
466 | index index.html;
467 | location / {
468 | try_files "/a" "/d" =404;
469 | }
470 | }
471 | ```
472 | 以上配置,会查找/tmp/a文件,如果都找不到则uri变成/d,并且响应码为http_code 404
473 |
474 | ## merge_slashes
475 | ```
476 | Syntax: merge_slashes on | off;
477 | Default: merge_slashes on;
478 | Context: http, server
479 | ```
480 | 开启或者关闭将请求中URI相邻的两个或者更多斜线合并成一个的功能
481 | 压缩URI对于前缀匹配和正则匹配的正确性是很重要的,没有开启这个功能时,请求//script/one.php不能被location /scripts/匹配
482 | 如果URI中包含base64编码内容,必须将斜线压缩调整成off,因为base64编码本身会使用"/"字符,然而出于安全方面的考虑,最好还是不要关闭压缩
483 | ```nginx
484 | merge_slashes on;
485 | location / {
486 | return 200 $uri;
487 | }
488 | ```
489 | ```curl
490 | curl 'http://127.0.0.1/a//b'
491 | ```
492 | 会输出/a/b
493 |
494 | ## location
495 | ```
496 | Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... }
497 | Default: —
498 | Context: server, location
499 | ```
500 | 根据请求的URI来设置配置
501 | * \~ 执行一个正则匹配,区分大小写,**匹配成功则停止,和顺序有关**
502 | * \~ \* 执行一个正则匹配,不区分大小写,**匹配成功则停止,和顺序有关**
503 | * ^~ 前缀匹配,区分大小写,**匹配成功则停止**
504 | * = 精准匹配,区分大小写,**匹配成功则停止**
505 | * /abc 常规字符串匹配,**如果有多个能匹配的话,使用匹配最长的那个,和顺序无关**
506 | * @ 定义一个命名的location,使用在内部定向时,如error_page
507 |
508 | 优先级:(从高到低)
509 | * =
510 | * ^~
511 | * \~ \* \~
512 | * /abc
513 |
514 | ```nginx
515 | location = /ab {
516 | return 200 "= /ab"
517 | }
518 | location /a {
519 | return 200 "/a"
520 | }
521 | location /ab {
522 | return 200 "/ab"
523 | }
524 | ```
525 | ```curl
526 | curl 'http://127.0.0.1/a'
527 | ```
528 | 返回http_code 200,消息体/a
529 | ```nginx
530 | location /a {
531 | return 200 "/a"
532 | }
533 | location /ab {
534 | return 200 "/ab"
535 | }
536 | ```
537 | ```curl
538 | curl 'http://127.0.0.1/ab'
539 | ```
540 | 返回http_code 200,消息体/ab
541 | ```nginx
542 | location /a {
543 | return 200 "/a"
544 | }
545 | location /ab {
546 | return 200 "/ab"
547 | }
548 | ```
549 | ```curl
550 | curl 'http://127.0.0.1/ab'
551 | ```
552 | 返回http_code 200,消息体/ab
553 | ```nginx
554 | location = /ab {
555 | return 200 "= /ab"
556 | }
557 | location ^~ /ab {
558 | return 200 "^~ /ab"
559 | }
560 | ```
561 | ```curl
562 | curl 'http://127.0.0.1/ab'
563 | ```
564 | 返回http_code 200,消息体= /ab
565 | ```nginx
566 | location ~ /ab {
567 | return 200 "~ /ab"
568 | }
569 | location ~* /ab {
570 | return 200 "~* /ab"
571 | }
572 | ```
573 | ```curl
574 | curl 'http://127.0.0.1/aB'
575 | ```
576 | 返回http_code 200,消息体~\* ab
577 |
578 | **=与^~不支持正则**
579 | ```nginx
580 | location = /abc$ { # $不是正则的结束标志
581 | return 200 $uri;
582 | }
583 | ```
584 | 可以使用前缀字符串或者正则表达式定义路径。使用正则表达式需要在路径开始添加"\~\*"前缀 (不区分大小写),或者"\~"前缀(区分大小写)。为了根据请求URI查找路径,nginx先检查前缀字符串定义的路径 (前缀路径),在这些路径中找到能最精确匹配请求URI的路径。然后nginx按在配置文件中的出现顺序检查正则表达式路径, 匹配上某个路径后即停止匹配并使用该路径的配置,否则使用最大前缀匹配的路径的配置
585 |
586 | **~与*~匹配成功则不继续匹配,并且和location的顺序有关**
587 | ```nginx
588 | location ~ /a {
589 | return 200 aaa;
590 | }
591 | location ~ /ab {
592 | return 200 bbb;
593 | }
594 | ```
595 | 请求uri为/abc则返回aaa
596 |
597 | ```nginx
598 | location ~ /ab {
599 | return 200 111;
600 | }
601 | location ~ /a {
602 | return 200 222;
603 | }
604 | ```
605 | 请求uri为/abc则返回111
606 | **注意**
607 |
608 | **^~ /a与/a不能同时写,会报错**
609 | ```nginx
610 | location = /a {
611 | return 200 $uri;
612 | }
613 | location ^~ /a {
614 | return 200 $uri;
615 | }
616 | ```
617 | ```nginx
618 | nginx: [emerg] duplicate location "/a"
619 | ```
620 |
621 | **^~与普通匹配都能匹配的情况,按照匹配的长度来**
622 | ```nginx
623 | location /ab {
624 | return 200 111;
625 | }
626 | location ^~ /a {
627 | return 200 222;
628 | }
629 | ```
630 | 请求uri为/abc,会返回111,请求uri为akl,会返回222
631 | ```nginx
632 | location /a {
633 | return 200 111;
634 | }
635 | location ^~ /ab {
636 | return 200 222;
637 | }
638 | ```
639 | 请求uri为/abc,会返回222,请求uri为a,会返回111
640 |
641 |
642 | 路径匹配在URI**规范化**以后进行,所谓规范化,就是先将URI中形如"%XX"的编码字符进行编码,再解析URI中的相对路径"."和".."部分,另外还可能会压缩相邻的两个或多个斜线成为一个斜线(需要merge_slashes on;)
643 | ```nginx
644 | location /abc+ {
645 | return 200 $uri;
646 | }
647 | ```
648 | ```curl
649 | curl 'http://127.0.0.1/abc%2B'
650 | ```
651 | 因为请求URI会规范化,所以将/abc%2B解析成/abc+,返回http_code 200,消息体/abc+
652 | ```nginx
653 | location /a {
654 | return 200 $uri;
655 | }
656 | ```
657 | ```curl
658 | curl 'http://127.0.0.1/b/../a'
659 | ```
660 | 因为请求URI会规范化,所以将/b/../a解析成/a,返回http_code 200,消息体/a
661 | 路径可以嵌套
662 | ```nginx
663 | location /{
664 | location /a {
665 | return 200 "a";
666 | }
667 | location /b {
668 | return 200 "b";
669 | }
670 | }
671 | ```
672 | ```curl
673 | curl 'http://127.0.0.1/a'
674 | ```
675 | 返回http_code 200,消息体/a
676 |
677 | 如果请求"\/"出现频繁,定义"location \= \/"可以提高这些请求的处理速度, 因为查找过程在第一次比较以后即结束
678 | ```nginx
679 | server {
680 | listen 80;
681 | location /a/ {
682 | proxy_pass http://127.0.0.1:81/b;
683 | }
684 | }
685 | server {
686 | listen 81;
687 | location / {
688 | return 200 $uri;
689 | }
690 | }
691 | ```
692 | ```curl
693 | curl 'http://127.0.0.1/a'
694 | ```
695 | 返回http_code 301
696 | ```nginx
697 | server {
698 | listen 80;
699 | location /a {
700 | proxy_pass http://127.0.0.1:81/b;
701 | }
702 | }
703 | server {
704 | listen 81;
705 | location / {
706 | return 200 $uri;
707 | }
708 | }
709 | ```
710 | ```curl
711 | curl 'http://127.0.0.1/a'
712 | ```
713 | 返回http_code 200,响应体/b
714 |
715 | ```nginx
716 | root /tmp;
717 | index index.css;
718 | server {
719 | listen 80;
720 | location / {
721 |
722 | }
723 | location /index.css {
724 | return 200 123;
725 | }
726 | }
727 | ```
728 | 请求uri为/,则uri变为/index.css,查找location /index.css,即使有/tmp/index.css,最后也会返回return 200 123
729 |
730 | ## server_tokens
731 | ```
732 | Syntax: server_tokens on | off | build | string;
733 | Default: server_tokens on;
734 | Context: http, server, location
735 | ```
736 | 开启或者关闭在响应头中输出nginx版本号
737 | ```
738 | HTTP/1.1 200 OK
739 | Server: nginx/1.14.0
740 | ```
741 | 参数build,如果编译时候configure -–build=8,则
742 | ```
743 | HTTP/1.1 200 OK
744 | Server: nginx/1.14.0 (8)
745 | ```
746 | 参数off会不显示具体nginx版本
747 | ```
748 | HTTP/1.1 200 OK
749 | Server: nginx
750 | ```
751 | 参数string在商业版本中使用
752 |
753 | ## client_max_body_size
754 | ```
755 | Syntax: client_max_body_size size;
756 | Default: client_max_body_size 1m;
757 | Context: http, server, location
758 | ```
759 |
760 | 设置允许客户端请求正文的最大长度,请求长度由Content-Length请求头指定。如果超过设定值,将返回413(Request Entity Too Large)。浏览器不能正确显示这个错误。size为0可以使nginx不检查客户端请求正文长度
761 |
762 | 当实际传的正文大于nginx限制,但是重写Content-Length,不会报错
763 |
764 | ```
765 | curl 'http://127.0.0.1' -H 'Content-Length: 1234
766 | ```
767 | 默认值1m的可接受最大Content-Length为1048576
768 |
769 | ## client_header_timeout
770 | ```
771 | Syntax: client_header_timeout time;
772 | Default: client_header_timeout 60s;
773 | Context: http, server
774 | ```
775 | 定义读取客户端请求头部的超时。如果客户端在这段时间内没有传送完整的头部到nginx, nginx将返回错误408 (Request Time-out)到客户端
776 |
777 | ## etag
778 | ```
779 | Syntax: etag on | off;
780 | Default: etag on;
781 | Context: http, server, location
782 | ```
783 | 开启或者关闭静态文件自动计算etag响应头
784 |
785 | 只是在静态文件中有效
786 |
787 | 默认情况下,请求静态文件会响应etag头,如ETag: "5bc887e1-2"
788 |
789 | ## return
790 | ```
791 | Syntax: return code [text];
792 | return code URL;
793 | return URL;
794 | Default: —
795 | Context: server, location, if
796 |
797 | ```
798 | 停止处理并返回指定code给客户端
799 |
800 | 该指令在debug的时候非常有用,比如nginx请求一个404的页面,如果想要知道nginx到底请求了什么路径,可以
801 | ```
802 | server {
803 | listen 80;
804 | location / {
805 | return 200 $request_filename;
806 | }
807 | }
808 | ```
809 | 在fastcgi下,也可以
810 | ```
811 | server {
812 | listen 80;
813 | location / {
814 | fastcgi_pass http://127.0.0.1:9000;
815 | include fastcgi.conf;
816 | return 200 $document_root$fastcgi_script_name;
817 | }
818 | }
819 | ```
820 | 可以返回各种nginx内部定义好的,和自己定义的变量
821 | ```
822 | server {
823 | listen 80;
824 | set $name 123;
825 | location / {
826 | return 200 $name;
827 | }
828 | }
829 | ```
830 | 返回非标准状态码444可以直接关闭连接而不返回响应头
831 | ```
832 | server {
833 | listen 80;
834 | location / {
835 | return 444;
836 | }
837 | }
838 | ```
839 | 请求127.0.0.1:80,请求过程为
840 | ```
841 | * Rebuilt URL to: http://127.0.0.1/
842 | * Trying 127.0.0.1...
843 | * TCP_NODELAY set
844 | * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
845 | > GET / HTTP/1.1
846 | > Host: 127.0.0.1
847 | > User-Agent: curl/7.61.0
848 | > Accept: */*
849 | >
850 | * Empty reply from server
851 | * Connection #0 to host 127.0.0.1 left intact
852 | curl: (52) Empty reply from server
853 | ```
854 | ```
855 | server {
856 | listen 80;
857 | location / {
858 | return 444 "abc";
859 | }
860 | }
861 | ```
862 | 请求127.0.0.1:80,请求过程为
863 | ```
864 | * Rebuilt URL to: http://127.0.0.1/
865 | * Trying 127.0.0.1...
866 | * TCP_NODELAY set
867 | * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
868 | > GET / HTTP/1.1
869 | > Host: 127.0.0.1
870 | > User-Agent: curl/7.61.0
871 | > Accept: */*
872 | >
873 | < HTTP/1.1 444
874 | < Server: nginx/1.12.2
875 | < Date: Tue, 06 Nov 2018 13:04:21 GMT
876 | < Content-Type: text/plain
877 | < Content-Length: 3
878 | < Connection: keep-alive
879 | <
880 | * Connection #0 to host 127.0.0.1 left intact
881 | abc
882 | ```
883 |
884 | 可以在指令中指定重定向的URL(0.8.42版本之后),状态码为301、302、303和307,或者指定响应体文本
885 |
886 | return http:\/\/uri 响应码为302
887 |
888 | 0.7.51版本以前只能返回204、400、402-406、408、410、411、413、416和500-504
889 |
890 | 直到1.1.16和1.0.13版本,307才被认为是一种重定向
891 |
892 | 1.13.0可以返回308
893 | ```
894 | server {
895 | listen 80;
896 | location / {
897 | return http://127.0.0.1:81;
898 | }
899 | }
900 | ```
901 | 请求127.0.0.1:80,会返回响应码302,如果请求支持重定向(如 curl -L ),则重定向到127.0.0.1:81
902 |
903 | **注意**
904 |
905 | 对于return重定向,要么写成return http:\/\/url这种形式,要么写成return 302 http:\/\/url这种形式(或者将302换成301、307)
906 |
907 | 如果return 200 http:\/\/url,则不会重定向,响应码是200,响应body体是"http:\/\/url"
908 |
909 | ## connection_pool_size
910 | ```
911 | Syntax: connection_pool_size size;
912 | Default: connection_pool_size 256|512;
913 | Context: http, server
914 | ```
915 | 允许微调为每个连接分配的内存,这个指令对nginx的性能影响非常小,一般不应该使用
916 |
917 | 默认值256在32位系统,512在64位系统
918 |
919 | ## interal
920 |
921 | ```
922 | Syntax: internal;
923 | Default: -
924 | Context: location
925 | ```
926 | 指定一个路径是否只能用于内部访问,如果是外部访问,客户端将收到404
927 | ```
928 | server {
929 | listen 80;
930 | location / {
931 | internal;
932 | return 200 "test";
933 | }
934 | }
935 | ```
936 | 请求127.0.0.1:80,返回的响应码为404而不是200
937 |
938 | 内部访问是
939 | - error_page、index、random_index、和try_files指令引起的重定向
940 | - 由后端服务器返回的X-Accel-Redirect响应头引起的重定向
941 | - 由ngx_http_ssi_module和ngx_http_addition_module模块的include virtual指令产生的子请求
942 | - 用rewrite指令对请求进行修改
943 |
944 | nginx限制每个请求只能最多进行10次内部重定向,以防配置错误引起请求处理出现问题,如果已经达到10次,nginx将返回500,同时日志中有rewrite or internal redirection cycle
945 |
--------------------------------------------------------------------------------
/日志管理.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [error_log](#error_log)
3 | * [log_format](#log_format)
4 | * [access_log](#access_log)
5 | * [log_not_found](#log_not_found)
6 |
7 | # error_log
8 | ```
9 | Syntax: error_log file [level];
10 | Default: error_log logs/error.log error;
11 | Context: main, http, mail, stream, server, location
12 | ```
13 | 日志级别严重性从轻到重顺序:debug、info、notice、warn、error、crit、alert、emerg
14 |
15 | 如果file设置为stderr,nginx将会将日志输出到标准错误输出
16 |
17 | 设置某个日志级别将会使指定级别和更高级别的日志都被记录下来,如指定error会使nginx记录所有的error、crit、alert、emerg级别消息
18 |
19 | debug日志级别需要configure --with-debug
20 |
21 | 特殊file值stderr可以将error_log输出到标准错误输出中,不过需要nignx的守护进程设置为off(damemon off;)
22 |
23 | # log_format
24 | ```
25 | Syntax: log_format name [escape=default|json|none] string ...;
26 | Default: log_format combined "...";
27 | Context: http
28 | ```
29 | 定义日志的格式,access_log默认使用的日志格式名字叫combined,可以定一个名字叫test的日志格式,然后让access_log使用test的日志格式
30 |
31 | nginx有一个默认的日志combined
32 | ```
33 | log_format combined '$remote_addr - $remote_user [$time_local] '
34 | '"$request" $status $body_bytes_sent '
35 | '"$http_referer" "$http_user_agent"';
36 | ```
37 |
38 | # access_log
39 | ```
40 | Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
41 | access_log off;
42 | Default: access_log logs/access.log combined;
43 | Context: http, server, location, if in location, limit_except
44 | ```
45 | ```
46 | server{
47 | access_log /tmp/nginx.access combined buffer=64k gzip=9 flush=1m;
48 | }
49 | ```
50 | 参数:
51 | - path:指定记录日志的位置
52 | - format:指定记录日志内容的格式,由log_format指定,默认的format名字为combined
53 | - buffer:指定缓存buffer大小,buffer的大小不能超过磁盘原子性写入大小
54 | - gzip:指定缓存压缩,如果gzip参数被使用,则buffer数据会先被压缩,然后再写入文件。gzip参数可以指定为1-9,1为最快,9最慢但是压缩比最大。默认情况下,gizp为1
55 | - flush:指定缓存到期时间,flush=1m为1分钟(如果达到1分钟,不管buffer满没满都将缓存写进日志文件)
56 | -
57 |
58 | 为访问日志设置路径、格式和缓冲区大小。在同一个配置层级里可以指定多个日志,特定值off会取消当前配置层级里面的所有access_log。如果没有指定日志格式则会使用预定义的combined
59 |
60 | 请求在处理结束时,会按请求路径的配置记录访问日志,如果请求处理期间产生了内部跳转,请求结束时的路径可能不同于原始的请求路径
61 |
62 | - 如果请求location a;在location a里面发生内部跳转到location b;在location b里面重新定义access_log或者error_log等,则location a里面的不会生效
63 |
64 | - 如果在location a里面proxy pass到location b,则a和b的都会记录,并且a的http_code是b给返回的
65 | ```
66 | server{
67 | location /a {
68 | access_log /tmp/a;
69 | rewrite ^/(.*)$ /b last; #请求这里会改变uri为/b,并且发生重新请求到location /b
70 | }
71 | location /b {
72 | access_log /tmp/b;
73 | }
74 | }
75 | ```
76 | 以上只有access_log /tmp/b会生效
77 |
78 | ```
79 | server{
80 | location /a {
81 | access_log /tmp/a;
82 | proxy_pass http://127.0.0.1/b; #发生请求到location /b
83 | }
84 | location /b {
85 | access_log /tmp/b;
86 | }
87 | }
88 | ```
89 | 以上access_log /tmp/b和access_log /tmp/a都会生效
90 |
91 |
92 | 如果指定gzip**或者**buffer参数,则写操作会被缓存
93 |
94 | 如果写操作缓存被使用,以下会发生实际写入文件的操作
95 | - 下一个日志没有被缓存
96 | - 如果到了flush指定的时间
97 | - 达到指定的buffer大小
98 | - 工作进程关闭或者打开(kill掉工作进程)
99 |
100 |
101 | 如果指定了缓存或者gzip,还指定了flush=1m,则在缓存不超缓存大小的情况下,会在1分钟后写入日志
102 |
103 | 如果日志数据被压缩,查看日志文件需要使用zcat filename
104 |
105 | 为了支持gzip功能,系统必须有zlib library模块
106 |
107 | 如果access_log的路径值使用变量,则不能使用buffer、gzip、flush,否则会报错
108 |
109 | 如果将nginx日志删掉,启动nginx和reload会新建这个日志文件;如果在运行期间删除nginx文件,则新请求不会创建nginx日志文件;日志路径包含变量的话,会在运行期间创建文件
110 |
111 | 如果运行期间日志被删除,则可以使用kill -USR1 nginx进程号 来创建nginx日志,-USR1对日志切割同样管用
112 |
113 | 在日志切割中,如果剪切access_log到access_log.old文件,然后给nginx的master进程发送-USR1信号,如果日志缓存启用,则日志缓存不管有没有到期或者达到buffer指定的大小,都缓存会写进access_log.old文件中
114 |
115 | **注意**,如果更改access_log的format,则要使用log_format定义,然后再使用
116 |
117 | ```
118 | server{
119 | log_format test '$remote_addr $status';
120 | access_log /tmp/nginx_access.log test;
121 | }
122 | ```
123 | **压缩的access日志解压**
124 | 可以使用gunzip来解压
125 |
126 | 1.cp nginx_access.log access.log.gz
127 |
128 | 2.gunzip access.log.gz
129 |
130 | 如果日志里面有gzip的内容,也有开启gzip前的明文内容,则无法解压
131 |
132 | # log_not_found
133 | ```
134 | Syntax: log_not_found on | off;
135 | Default:
136 | log_not_found on;
137 | Context: http, server, location
138 | ```
139 | 如果为on,当静态资源发生404的时候,会在error_log日志中记录error级别的错误信息
140 | ```
141 | 2019/05/28 16:42:17 [error] 2941#0: *9 open() "/tmp/aa.php" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "GET /aa.php HTTP/1.1", host: "127.0.0.1"
142 |
143 | ```
144 | 即使为off,在请求fastcgi情况下发生404,也会记录错误信息
145 | ```
146 | 2019/05/28 16:41:24 [error] 2923#0: *5 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 127.0.0.1, server: , request: "GET /aa.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "127.0.0.1"
147 | ```
148 |
--------------------------------------------------------------------------------
/连接处理方法IO.md:
--------------------------------------------------------------------------------
1 | ## 目录
2 | * [概述](#概述)
3 | * [几种可选方法介绍](#几种可选方法介绍)
4 | * [use](#use)
5 | * [如何查看当前nginx的IO方法](#如何查看当前nginx的IO方法)
6 |
7 | # 概述
8 | nginx支持多种连接处理IO方法,特定IO方法的可用性取决于所使用的平台。如果平台支持多种IO方法,nginx会自动选择最有效的IO方法。但是,如果需要的话,也可以通过指令use指定具体的IO方法
9 |
10 | 如果不指定use,则选择系统和nginx可以支持的最优IO模型
11 |
12 | configure编译选项中可以选择--without-poll_module、--with-poll_module、--without-select_module、--with-select_module使其强制使用或者禁止使用某IO模型
13 |
14 | 如果使用--without-select_module,则不可以使用use select指令了,报错提示:invalid event type "select"
15 |
16 | 如果使用--with-select_module,则可以使用use epoll指令,最后nginx使用的是epoll的IO模型
17 |
18 | # 几种可选方法介绍
19 | **select**
20 |
21 | 标准方法。如果平台没有更有效的方法的话,则这个方法会自动被选择和构建
22 |
23 | **poll**
24 |
25 | 标准方法。如果平台没有更有效的方法的话,则这个方法会自动被选择和构建
26 |
27 | **kqueue**
28 |
29 | 优先选择的有效方法(在FreeBSD 4.1+,OpenBSD 2.9+,NetBSD 2.0和macOS平台上)
30 |
31 | **epoll**
32 |
33 | 优先选择的有效方法(在Linux 2.6+平台上)
34 |
35 | **/dev/poll**
36 |
37 | 优先选择的有效方法(在Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+,和Tru64 UNIX 5.1A+平台上)
38 |
39 | **eventport**
40 |
41 | 建议使用/dev/poll替代,该IO模型用于Solaris 10+
42 |
43 | # use
44 | ```
45 | Syntax: use method;
46 | Default: —
47 | Context: events
48 | ```
49 | ```
50 | events{
51 | use select;
52 | #use epoll;
53 | }
54 | ```
55 | 通常不会指定,因为nginx会默认选择最优的方案
56 |
57 | # 如何查看当前nginx的IO方法
58 |
59 | ```
60 | server{
61 | ...
62 | error_log /tmp/nginx_error.log debug; #注意,debug级别需要configure --with-debug
63 | ...
64 | }
65 | ```
66 | 可以指定error_log为debug级别,然后会有debug信息
67 | ```
68 | 2018/10/23 23:27:40 [debug] 90859#0: epoll add event: fd:7 op:1 ev:00002001
69 | ```
70 |
--------------------------------------------------------------------------------