你需要知道的Nginx配置二三事

做服务端开发的,工作中难免会遇到处理Nginx配置相关问题。在配置Nginx时,我一直本着“照葫芦画瓢”的原则,复制已有的配置代码,自己修修改改然后完成配置需求,当有人问起Nginx相关问题时,其实仍然一无所知。为此在工作之余,花了一周的时间阅读Nginx配置相关文章,整理成自己的学习笔记如下:

nginx是什么

Nginx是俄罗斯人Igor Sysoev基于C语言编写的十分轻量级的HTTP服务器,它主要有以下特点: 
- 它是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器; 
- Nginx使用异步事件驱动的方法来处理请求,Nginx的模块化事件驱动架构可以在高负载下提供更可预测的性能; 
- 作为Web服务器,Nginx处理静态文件、索引文件,自动索引的效率非常高 
- 作为反向代理服务器,Nginx可以实现反向代理加速,提高网站运行速度 
- 作为负载均衡服务器,Nginx既可以在内部直接支持Rails和PHP,也可以支持HTTP代理服务器对外进行服务,同时还支持简单的容错和利用算法进行负载均衡 
- Nginx是专门为性能优化而开发的,非常注重效率,Nginx在官方测试的结果中,能够支持五万个并行连接,而在实际的运作中,可以支持二万至四万个并行链接 
- 在高可用性方面,Nginx支持热部署,启动速度特别迅速,因此可以在不间断服务的情况下,对软件版本或者配置进行升级

nginx如何配置?

Nginx的配置文件默认存放路径是etc/nginx/nginx.conf,可以在Nginx启动时添加参数–conf-path=PATH来更改nginx.conf文件的存放路径。nginx.conf中的配置信息主要包含以下五个部分:

  • main(全局设置):主要是包括Nginx工作进程,日志的配置以及server,location中一些共用的配置
  • events(连接设置):主要包括Nginx连接信息的配置
  • server(主机设置):主要是包括主机名称,Ip,路径解析,http请求头设置,反向代理等配置
  • upstream(上游服务器设置):主要为反向代理服务器信息、负载均衡等相关配置
  • location(URL匹配):特定URL的匹配设置

以上每部分包含若干个条指令,他们之间的关系是:server继承main,location继承server,main部分设置的指令将影响其它所有部分的设置,server部分的设置将影响到location部分的设置。upstream既不会继承指令也不会被继承,它有自己的特殊指令,不需要在其他地方的应用。

以下是我整理的关于Nginx五个主要模块的所有基础参数设置,并用#注释的方式对每个参数的含义做了详细的阐述:

Nginx基础配置参数详解:

  1 ################################################################################################################## 
  2 # main全局配置                                                                                                    #
  3 ##################################################################################################################
  4 
  5 user  www www;  #默认为nobody
  6 # 设置nginx工作进程的用户
  7 
  8 worker_processes  2; # 默认为1
  9 # 设置worker角色的工作进程的个数,正常情况下可以设置成cpu的内核数,最多设置为8个;
 10 # 也可以将worker_processes的值设为auto,这样nginx会自动检测CPU核数并打开相同数量的worker进程;
 11 # 当nginx添加了SSL证书时,最好要打开多个worker进程。SSL握手会进行硬盘I/O操作。所以打开多个worker进程有利于性能的提升;
 12 
 13 worker_cpu_affinity 01 10; 
 14 # 通过设置cpu粘性来降低由于多CPU核切换造成的寄存器等现场重建带来的性能损耗,上述设置表示第一个worker进程用第一个cpu,第二个worker进程进程使用第二个cpu
 15 
 16 worker_rlimit_nofile; # 默认为操作系统的限制(65535)
 17 # 设置每个worker进程的最大打开文件数(句柄)限制
 18 
 19 error_log  logs/error.log error;    
 20 # 配置错误日志路径以及打印级别(debug | info | notice | warn | error | crit | alert | emerg)
 21 # 生产场景一般是warn | error | crit 这三个级别之一,级别太低会有太多IO消耗,影响效率
 22 
 23 pid logs/nginx.pid; 
 24 # pid文件为文本文件,内容只有一行, 记录了该进程的ID,根据PID文件的内容,准确判断进程是否正在运行,防止意外启动多个进程实例。
 25 # 只有获得pid文件(固定路径固定文件名)写入权限(F_WRLCK)的进程才能正常启动并把自身的PID写入该文件中,其它同一个程序的多余进程则自动退出。
 26 
 27 ################################################################################################################## 
 28 # events模块中包含nginx中所有处理连接的设置                                                                           #
 29 ##################################################################################################################
 30 
 31 events {
 32     use epoll;    
 33     # 用于设置处理客户端请求的轮询方法
 34     # 在Linux操作系统下,nginx默认使用epoll事件模型
 35     # 同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue
 36     # 在操作系统不支持这些高效模型时才使用select
 37 
 38     worker_connections  2048;  #默认为512
 39     # 设置可由一个worker进程同时打开的最大连接数。但不能超过worker_rlimit_nofile的设置
 40 
 41     accept_mutex on;  # 默认为on
 42     # 当一个新连接到达时,如果激活了accept_mutex,那么多个Worker将以串行方式来处理,其中有一个Worker会被唤醒,其他的Worker继续保持休眠状态;
 43     # 如果没有激活accept_mutex,那么所有的Worker都会被唤醒,不过只有一个Worker能获取新连接,其它的Worker会重新进入休眠状态,[thundering herd现象](https://en.wikipedia.org/wiki/Thundering_herd_problem)
 44 
 45     accept_mutex_delay 500ms; # 默认为500ms
 46     # 当accept_mutex功能启用后,只有一个持有mutex锁的worker进程会接受并处理请求,其他worker进程等待。accept_mutex_delay指定的时间就是这些worker进程的等待时间,过了等待时间下一个worker进程便取得mutex锁,处理请求。
 47 
 48     multi_accept on # 默认为off
 49     # multi_accept可以让nginx worker进程尽可能多地接受请求,提高性能
 50     # 如果设置为on,可以让worker进程一次性地接受监听队列里的所有请求,然后处理
 51     # 如果multi_accept的值设为off,那么worker进程必须一个一个地接受监听队列里的请求
 52     # 如果web服务器面对的是一个持续的请求流,那么启用multi_accept可能会造成worker进程一次接受的请求大于worker_connections指定可以接受的请求数。这就是overflow,这个overflow会造成性能损失,overflow这部分的请求不会受到处理
 53 }
 54 
 55 ################################################################################################################## 
 56 # 提供http服务相关的一些配置参数                                                                                      #
 57 ##################################################################################################################
 58 
 59 http {
 60 
 61     #################################################################################### 
 62     # 基本配置                                                                          #
 63     ####################################################################################
 64 
 65     include  mime.types; 
 66     # include可以包含若干子配置文件,实现不同需求配置独立,可以将不同的server配置在不同的conf文件里
 67     # mime.types文件列出针对不同的请求文件返回的HTTP response的Content-Type的Accept值
 68     # 除非服务端Web程序手动设置了Content-Type,如果Web程序没设置,则会从mime.types中匹配返回
 69     # 如果mime.types中也没找到对应文件的扩展名的话,就使用默认的default_type
 70 
 71     default_type  application/octet-stream; 
 72     # 如果在mime.types的配置中没有找到响应请求文件的格式,则走default_type
 73 
 74     types_hash_max_size 2048;
 75     # 设置散列表的冲突率。
 76     # types_hash_max_size越大,就会消耗更多的内存,但散列key的冲突率会降低,检索速度就更快。
 77     # types_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能上升。
 78 
 79     server_tokens off;
 80     # 返回错误页面时是否在Server中注明Nginx版本
 81 
 82     server_names_hash_bucket_size 64;
 83     # 为了提高快速寻找到相应server_name的能力,Nginx 使用散列表来存储server_name,server_names_hash_bucket_size设置了每个散列桶占用的内存大小。
 84 
 85     server_name_in_redirect off;
 86     # 重定向主机名称的处理.该配置需要配合server_name使用.
 87     # 设置为on时,表示在重定向请求时会使用stream里配置的第一个主机名代替原先请求中的Host头部,而当关闭时,表示在重定向请求时使用请求本身的Host头部。
 88 
 89 
 90 
 91     #################################################################################### 
 92     # 日志配置                                                                         #
 93     ####################################################################################
 94 
 95     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '   
 96                       '$status $body_bytes_sent "$http_referer" '
 97                       '"$http_user_agent" "$http_x_forwarded_for"';
 98     # 定义日志nginx日志文件的打印格式并命名为变量main
 99 
100     access_log  logs/access.log  main;   
101     # access_log指定nginx的访问日志的存放路径文件以及使用的日志文件格式
102 
103     #access_log off;   
104     # 为了提高效率,可以将访问日志关掉
105 
106     access_log /data/logs/nginx-access.log buffer=32k flush=5s;
107     # buffer和flush可以设置缓存日志的刷盘策略,日志超过32k才刷盘,如果没满32k,但是超过5s也自动刷盘
108 
109     rewrite_log on; # 默认是off
110     # 开启或者关闭rewrite模块指令执行的日志,如果开启,则重写将记录下notice等级的日志到nginx 的error_log中
111 
112     #################################################################################### 
113     # 高效文件传输                                                                        #
114     ####################################################################################
115 
116     sendfile on; 
117     # 当一个程序需要传输文件时,Linux内核首先将文件数据缓冲,然后将文件数据传送给程序缓冲,最后程序将文件数据传输到目的地。
118     # Sendfile方法是一种数据传输的更高效的方法,数据在内核中的文件描述符之间传输
119     # 这种方法的结果是改善了对操作系统资源的利用,提高Nginx静态资源托管效率,直接在内核空间完成文件发送,不需要先read再write,没有上下文切换开销
120 
121     tcp_nopush on; 
122     # TCP_NOPUSH是FreeBSD的一个socket选项,对应Linux的TCP_CORK,Nginx里统一用tcp_nopush来控制它,并且只有在启用了sendfile之后才生效。
123     # 启用它之后,数据包会累计到一定大小之后才会发送,减小了额外开销,提高网络效率
124 
125     tcp_nodelay on;
126     # TCP_NODELAY也是一个socket选项,启用后会禁用Nagle算法,尽快发送数据,某些情况下可以节约200ms
127     # Nagle算法原理是:在发出去的数据还未被确认之前,新生成的小数据先存起来,凑满一个 MSS 或者等到收到确认后再发送
128     # Nginx 只会针对处于keep-alive状态的TCP连接才会启用tcp_nodelay
129 
130     keepalive_timeout  65; 
131     # 长连接的时间限制,http是基于tcp实现的,这个参数用于设置tcp长连接的时间长度
132     # 客户端可以设置http服务要不要走长连接,通过设置请求头Connection=keep-alive实现的,http1.0默认是关闭的,http1.1默认是打开的
133     # 谷歌浏览器同时最多有6个tcp连接
134     # keepalive_timeout时间不能设置太长,因为太长会长时间占用tcp连接不释放,导致服务器的tcp连接不够用;也不能太短,如果太短会导致一些大文件上传接口因为上传一半而中断;
135 
136     #################################################################################### 
137     # http_proxy 设置,client相关配置                                                    #
138     ####################################################################################
139 
140     client_max_body_size   10m;
141     # 允许客户端请求的最大单文件字节数限制。如果有上传较大文件的需求,尽量设置大一些
142 
143     client_body_buffer_size   128k; 
144     # 缓冲区代理用户端请求的最大字节数
145 
146     client_header_timeout 60; 
147     # 指定等待client发送一个请求头的超时时间,仅当在一次read中,没有收到请求头,才会算成超时。如果在超时时间内,client没发送任何东西,nginx返回HTTP状态码408(“Request timed out”)
148 
149     client_body_timeout 60; 
150     # 该指令设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后,nginx返回HTTP状态码408(“Request timed out”)
151 
152     #################################################################################### 
153     # http_proxy 设置,server相关配置                                                    #
154     ####################################################################################
155 
156     proxy_connect_timeout  60; 
157     # 该指令设置与upstream server的连接超时时间,有必要记住,这个超时不能超过75秒
158 
159     proxy_send_timeout   75; 
160     # 这个指定设置了发送请求给upstream服务器的超时时间。超时设置不是为了整个发送期间,而是在两次write操作期间。如果超时后,upstream没有收到新的数据,nginx会关闭连接
161 
162     proxy_read_timeout   75; 
163     # 该指令设置与代理服务器的读超时时间。它决定了nginx会等待多长时间来获得请求的响应。这个时间不是获得整个response的时间,而是两次reading操作的时间,默认值60s
164 
165     proxy_upstream_fail_timeout 10; 
166     # Upstream模块下server指令的参数,设置了某一个upstream后端失败了指定次数(max_fails)后,该后端不可操作的时间,默认为10秒
167 
168     proxy_buffer_size   4k; 
169     # 设置代理服务器(nginx)从后端realserver读取并保存用户头信息的缓冲区大小,默认与proxy_buffers大小相同,其实可以将这个指令值设的小一点
170 
171     proxy_buffers   4 32k; 
172     # proxy_buffers缓冲区,4个缓存,每个大小限制为32k。
173 
174     proxy_busy_buffers_size   64k; 
175     # 高负荷下缓冲大小(proxy_buffers*2)
176 
177     proxy_temp_file_write_size  64k; # 默认为1024M
178     # 当proxy_buffers放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M
179     # 它与proxy_cache没有关系,大于这个值,将从upstream服务器传回。设置为0禁用
180 
181     proxy_temp_path   /usr/local/nginx/proxy_temp 1 2; 
182     # 指定缓存写到那个目录
183 
184     #################################################################################### 
185     # gzip压缩功能设置                                                                   #
186     ####################################################################################
187 
188     gzip on;      
189     # 开启gzip压缩输出,减少网络传输,客户端通过设置请求头Accept-Encoding=gzip, deflate, br来支持gzip压缩
190 
191     gzip_static on; 
192     # nginx对于静态文件的处理模块,该模块可以读取预先压缩的gz文件,这样可以减少每次请求进行gzip压缩的CPU资源消耗。
193     # 该模块启用后,nginx首先检查是否存在请求静态文件的gz结尾的文件,如果有则直接返回该gz文件内容
194 
195     gzip_disable "msie[1-6].";  
196     # IE6的某些版本对gzip的压缩支持很不好,会造成页面的假死,为了确保其它的IE6版本不出问题,所以建议加上gzip_disable的设置
197 
198     gzip_min_length 1k; 
199     # 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大
200 
201     gzip_buffers    4 16k; 
202     # 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存
203 
204     gzip_http_version 1.0; 
205     # 用于识别http协议的版本,早期的浏览器不支持Gzip压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项。
206     # 如果你用了Nginx的反向代理并期望也启用Gzip压缩的话,由于末端通信是 http/1.0,故请设置为 1.0
207 
208     gzip_comp_level 6; 
209     # gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
210 
211     gzip_types text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript
212     application/xml; 
213     # 匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的
214 
215     gzip_vary on; 
216     # 和http头有关系,会在响应头加个Vary:Accept-Encoding,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据
217 
218     gzip_proxied any 
219     # Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头
220 
221     ################################################################################## 
222     # FastCGI 设置,为了保证Nginx下PHP环境的高速稳定运行,需要添加一些FastCGI优化指令          #
223     ##################################################################################
224 
225     fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m inactive=5m; 
226     # 为FastCGI缓存指定一个文件路径、目录结构等级、关键字区域存储时间和非活动删除时间
227 
228     fastcgi_connect_timeout 300;  
229     # 指定连接到后端FastCGI的超时时间
230 
231     fastcgi_send_timeout 300;     
232     # 指定向FastCGI传送请求的超时时间,这个值是已经完成两次握手后向FastCGI传送请求的超时时间 
233 
234     fastcgi_read_timeout 300;     
235     # 指定接收FastCGI应答的超时时间,这个值是已经完成两次握手后接收FastCGI应答的超时时间
236 
237     fastcgi_buffer_size 64k;      
238     # 用于指定读取FastCGI应答第一部分需要多大的缓冲区,这个值表示将使用1个64KB的缓冲区读取应答的第一部分(应答头),可以设置为fastcgi_buffers选项指定的缓冲区大小
239 
240     fastcgi_buffers 4 64k;     
241     # 指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求。
242     # 如果一个PHP脚本所产生的页面大小为256KB,那么会为其分配4个64KB的缓冲区来缓存;如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp指定的路径中。
243     # 一般这个值应该为站点中PHP脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“16 16k”、“4 64k”等
244 
245     fastcgi_temp_file_write_size 128k; 
246     # 表示在写入缓存文件时使用多大的数据块,默认值是fastcgi_buffers的两倍 
247 
248     fastcgi_cache TEST;  
249     # 表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502错误的发生
250 
251     fastcgi_cache_valid 200 302 1h;
252     # 指定code为200,302的响应缓存为一小时 
253 
254     fastcgi_cache_valid 301 1d;  
255     # 指定code为301的缓存有效时间为1天
256 
257     fastcgi_cache_valid any 1m; 
258     # 其它缓存有效时间都为1分钟
259 
260     ################################################################################## 
261     # 设定负载均衡后台服务器列表                                                       #
262     ################################################################################## 
263 
264     upstream  backend  { 
265         ip_hash;    # 默认为round-robin
266         # 负载均衡处理方式,一共有三种方式:
267         # (1)round-robin(轮训请求方式)
268         # (2)ip_hash(回话持久化方式,这个方法保证从同一个客户端发起的请求总是定向到同一台服务器)
269         # (3)least_conn(最少连接方式,找连接最少的服务进行处理)
270 
271         server   192.168.10.100:8080 max_fails=2 fail_timeout=30s weight=2;
272         server   192.168.10.101:8080 max_fails=2 fail_timeout=30s weight=3;
273         server   192.168.10.101:8080 backup
274         server   192.168.10.101:8080 down;
275         # weight设置每个服务的命中几率,默认是1;
276         # backup表示备份服务,只有所有的非备份不能使用时,会启动该服务,down表示当前服务永远不参与负载;
277         # max_fails表示容许请求失败的次数,当超过该次数时将暂停一定时间(fail_timeout)
278     }
279 
280     ################################################################################## 
281     # server虚拟主机配置                                                               #
282     ##################################################################################
283 
284     server {
285         ############################################ 
286         # 基本配置                                   #
287         ############################################
288 
289         listen  80 default_server; # 默认为80
290         # 监听端口设置,小于1024的要以root启动,
291         # default_server表示如果找不到对应端口的server_name,则默认走这个匹配
292 
293         server_name  itoatest.example.com;
294         # 一个nginx可以配置多个server,nginx通过检查请求header中host来匹配每个server的server_name决定走哪个server,
295         # 如果没有任何一个server可以匹配,则会选择第一个server做匹配。默认匹配可以通过listen中添加defalut_server来改变。
296         # server_name有四种匹配方式:
297         # (1)精确匹配(itoatest.example.com)
298         # (2)星号开头的最长的通配符名称(*.example.org)
299         # (3)星号结束的最长的通配符名称(mail.*)
300         # (4)正则表达式匹配(~^wwwd+.example.net$,正则表达式必须以~开头)
301 
302         root   /apps/oaapp;
303         # 见下文location讲解
304 
305         allow 223.252.218.196;
306         allow 59.111.28.48/32;
307         # allow表示允许某个ip或ip段访问
308 
309         deny all
310         # deny表示禁止某个ip或者ip段访问
311 
312         error_page   500 502 503 504  /50x.html;
313         error_page   403    http://example.com/forbidden.html;
314         # 这个参数可以为错误代码指定相应的错误页面 
315 
316         charset utf-8;
317         # 设置http头信息的charset编码
318 
319         if ($request_method = POST) {
320             return 405;
321         } 
322         # 关于if的使用请看下文[Nginx中如何使用变量?]
323 
324         ############################################ 
325         # location特定的URL对应的一系列配置项          #
326         ############################################
327         location /i/ {       # 关于location中的路径匹配规则以及匹配优先级请看下文[Nginx中location部分URL如何匹配?]
328             root   /apps/oaapp;   
329             #alias  /apps/oaapp/;
330             # root和alias都可以用来指定请求资源的真实路径。
331             # 区别是root最后得到的资源地址是root的值加上location的值,而alias正如其名,alias指定的路径是location的别名,不管location的值怎么写,资源的真实路径都是 alias 指定的路径。
332             # 比如当访问http://itoatest.example.com/i/hello.gif这个地址时,如果是root,资源的真实路径是/apps/oaapp/i/hello.gif;如果是alias真实路径是/apps/oaapp/hello.gif;
333             # alias只能作用在location中,而root可以存在server、http和location中
334             # alias 后面必须要用 “/” 结束,否则会找不到文件,而 root 则对 ”/” 可有可无
335 
336             index  index.jsp index.html index.htm;
337             # 当用户请求的是http://itoatest.example.com/i/这个地址时,就会自动在root配置指令指定的文件系统目录下依次寻找 index.jsp 和 index.html,index.htm这三个文件,直到找到一个并返回
338 
339             autoindex on; # 默认为off
340             # 当index指定的文件都找不到时,如果开启autoindex,那么则会生成一个root所指目录下的“目录索引”的html并返回,如果没有开启,则会返回forbidden
341 
342             autoindex_exact_size off # 默认为on
343             # 只有在autoindex开启时才起作用,默认为on,显示出文件的确切大小,单位是bytes。改为off后,显示出文件的大概大小,单位是kB或者MB或者GB
344 
345             autoindex_localtime on # 默认为off
346             # 只有在autoindex开启时才起作用,默认为off,显示的文件时间为GMT时间。改为on后,显示的文件时间为文件的服务器时间
347 
348             proxy_pass  http://backend;
349             # 请求转向某个upstream定义的负载均衡的服务器列表,如果只有一台服务器的话,也可以直接写成proxy_pass http://ip:port;
350 
351             rewrite ^/i/(.*) /$1 break;
352             # rewrite 的作用是修改 $uri,具体细节请看下文[rewrite如何重写url?]
353 
354             proxy_redirect off; # 默认是default
355             proxy_redirect http://192.168.10.101:8080/i/wuman/ http://itoatest.example.com/i/wuman/
356             # 如果需要修改从被代理服务器传来的应答头中的"Location"和"Refresh"字段,可以用这个指令设置,分为三种情况:
357             #(1)proxy_redirect off表示不修改服务端的redirect地址
358             #(2)proxy_redirect default 将根据location和proxy_pass的设置来决定
359             #(3)可以自己设置不同的替换规则
360 
361             proxy_set_header  Host  $host; #默认是$proxy_host
362             # 可以通过三个变量对Host进行设置:
363             #(1)$proxy_host,表示是反向代理后的host,就是proxy_pass后面跟的host
364             # (2) $host首先从请求头中获取Host值,如果没有则选择server_name
365             # (3) $http_host是直接从请求头中获取,所以可能为空,如果是非80/443端口的时候,$http_host = $host:$port
366 
367             proxy_set_header  X-Real-IP  $remote_addr;  
368             # 由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址;
369             # 所以我们可以设置一个请求头X-Real-IP,通过获取这个请求头就可以拿到客户端的真实ip
370 
371             proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
372             # 上述的意思增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖
373             # 如果每次代理都使用上述配置,那么X-Forwarded-For可以获取到经过多次代理后的客户多IP以及多层代理nginx的IP:IP0, IP1, IP2...
374             # 所以proxy_set_header也是获取真实客户端ip的一种方法
375 
376             proxy_set_header X-Forwarded-Proto  https;
377             # 请求标头可帮助您识别客户端与您的负载均衡器连接时所用的协议,并随后将标题传递到您的服务器
378 
379             proxy_set_header X-Forwarded-Host $host
380             # 可以帮助您识别客户端与您的负载均衡器连接时所用的host,并随后将标题传递到您的服务器
381 
382             proxy_set_header X-Forwarded-Host $port
383             # 可以帮助您识别客户端与您的负载均衡器连接时所用的port,并随后将标题传递到您的服务器
384 
385             proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; # 默认是error timeout
386             # 指定在什么情况下将请求应传递到下一个服务器,如果设置为off表示在任何情况下都不需要传递
387             # error表示发生错误时,将请求传递到下一个服务器
388             # timeout表示发生请求或者响应超时时,将请求传递给下一个服务器
389             # invalid_header表示服务器返回空响应或无效响应时,将请求传递给下一个服务器
390             # http_code表示服务器返回对应的code时将请求传递到下一个服务器
391 
392             proxy_next_upstream_timeout 30 # 默认是0
393             # 限制请求可以传递到下一个服务器的时间,0表示关闭限制
394 
395             proxy_next_upstream_tries 2 # 默认为0
396             # 限制将请求传递到下一个服务器的可能尝试次数, 0值关闭此限制
397 
398         }
399 
400         location ~ .*.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$   
401         {   
402             root /apps/oaapp;
403 
404             expires      7d;
405             # 对于站点中不经常修改的静态内容(如图片,JS,CSS),可以在服务器中设置expires过期时间,控制浏览器缓存,达到有效减小带宽流量,降低服务器压力的目的
406         }
407 
408         location = /50x.html {
409             root   html;
410         }
411 
412         location = /video {
413             directio 4m;  # 该路径下所有大于4M的文件不直接从磁盘读取,不走缓存
414             # Direct I/O是文件系统的一个功能,它允许程序绕过内核缓存,直接在硬盘上读写数据
415             # 这可以充分利用CPU频数,改善缓存的有效性,Directo I/O适用于访问率少的数据。这些数据不需要缓存在任何位置
416             # 在http, server和location当中都可以定义
417             # 如果某个请求是通过directo I/O,那么这个请求不能使用sendfile功能
418         }
419     }
420 }
View Code

nginx中location部分url如何匹配?

location主要是匹配url中除去server_name(主机名)后的部分,其中关于url的匹配规则有以下几种: 
- 精确匹配:以“=”开头表示精确匹配 
- 开头匹配:^~ 表示uri以某个常规字符串开头,不是正则匹配 
- 区分大小写的正则匹配:~开头表示区分大小写的正则匹配 
- 不区分大小写的正则匹配:~* 开头表示不区分大小写的正则匹配 
- 通用匹配:匹配url的前面部分

对于上述五类匹配,它们之间的匹配顺序和优先级关系如下: 
- 不同类型之间匹配和location的顺序无关,只和优先级有关,各种匹配规则的优先级关系是: [精确匹配] > [开头匹配] > [正则匹配] > [通用匹配]; 
- 除了通用匹配,开头匹配以外,相同类型的匹配优先级只和顺序有关,排在前面的优先匹配; 
- 通用匹配和开头匹配的优先级与通用匹配的最长字符串有关,通用字符串越长,匹配优先级越高;

下面是我设置的几个location,并测试和验证以上匹配规则:

 1 server {
 2     listen       80 default_server;
 3     server_name  dev.zdp.com;
 4 
 5     # 通用匹配  [匹配规则0]
 6     location  /
 7     {
 8         return 302 https://dashboard.youdata.com;
 9     }
10 
11     # 通用匹配  [匹配规则1]
12     location  /hello
13     {
14         return 302 https://dashboard.youdata.com;
15     }
16 
17     # 通用匹配  [匹配规则2]
18     location  /hello/no
19     {
20         return 302 https://dev.youdata.com;
21     }
22 
23     # 不区分大小写的正则匹配  [匹配规则3]
24     location ~* /hello/y[a-e][a-z][1-9]
25     {
26         return 302 https://test.youdata.com;
27     }
28 
29     # 区分大小写的正则匹配  [匹配规则4]
30     location ~ /hello/y[A-E][E-Z][1-9]
31     {
32         return 302 https://pre.youdata.com;
33     }
34 
35     # 区分大小写的正则匹配  [匹配规则5]
36     location ~ /hello/y[a-e][e-z]
37     {
38         return 302 https://pre163.youdata.com;
39     }
40 
41     # 开头匹配  [匹配规则6]
42     location ^~ /hello/yes
43     {
44         return 302  https://youdata.netease.com;
45     }
46 
47     # 开头匹配  [匹配规则7]
48     location ^~ /hello/yesno
49     {
50         return 302  https://youdata.163.com;
51     }
52 
53     # 精确匹配 [匹配规则8]
54     location = /hello
55     {
56         return 302  https://www.baidu.com;    
57     }
58 
59 }
View Code

location用例测试: 
- “http://dev.zdp.com/hello” ——- 精确匹配优先,命中[匹配规则8] 
- “http://dev.zdp.com/hello/yesnoOk” ——- 开头匹配优先,开头匹配同时满足条件时,长优先,命中[匹配规则7] 
- “http://dev.zdp.com/hello/yesOk” ——- 开头匹配优先,命中[匹配规则6] 
- “http://dev.zdp.com/hello/yaz” ——- 正则匹配,命中[匹配规则5] 
- “http://dev.zdp.com/hello/yAZ3” ——- 正则匹配,按照location顺序匹配,命中[匹配规则3] 
- “http://dev.zdp.com/hello/no” ——- 通用匹配,按照匹配长度优先,命中[匹配规则2] 
- “http://dev.zdp.com/hello/Ok” ——- 通用匹配,命中[匹配规则1] 
- “http://dev.zdp.com/everyone” ——- 通用匹配,所有其它匹配不满足时,命中[匹配规则0]

nginx中rewrite命令如何重写url?

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{},location{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如:

http://dev.zdp.com/a/we/index.php?id=1&u=str => rewrite只能对/a/we/index.php部分重写

重写用法:

server {
    rewrite 规则 定向路径 重写flag;
}

location {
    rewrite 规则 定向路径 重写flag;
}
rewrite的执行顺序
  • 执行server块的rewrite指令;
  • 执行location匹配;
  • 执行选定的location中的rewrite指令,如果location中rewrite指令没有break的flag,则会根据当前rewrite路径重新匹配location;
  • 如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件,循环最多不会超过10次;
rewrite的flag标志
  • last: 停止处理当前location中的ngx_http_rewrite_module指令集(rewrite,return等),并开始重新搜索与更改后的URI相匹配的location
  • break : 停止处理当前location中的ngx_http_rewrite_module指令集(rewrite,return等),不会重新搜索
  • redirect : 返回302临时重定向,地址栏会显示跳转后的地址
  • permanent : 返回301永久重定向,地址栏会显示跳转后的地址
  • default: 默认标志,继续会处理当前location中的ngx_http_rewrite_module指令集(rewrite,return等),如果没有return,会开始重新搜索与更改后的URI相匹配的location
rewrite的测试用例
 1 server {
 2     listen       80 default_server;
 3     server_name  dev.zdp.com;
 4 
 5     set $flag="default";
 6 
 7     # 当我们访问http://dev.zdp.com/test1/helloworld时,对于不同flag变量返回的结果如下:
 8     # 当$flag="default"时,会执行后续的ngx_http_rewrite_module命令,所以会重定向到https://newke.com;
 9     # 当$flag="last"时,不会执行后续的ngx_http_rewrite_module命令,但是会重新匹配location,所以重定向到https://www.baidu.com;
10     # 当$flag="break"时,不会执行后续的ngx_http_rewrite_module命令,所以没有找到匹配,失败
11     location /test1
12     {
13         rewrite ^/test1/([^/]+?) /test2/$1 $flag;
14         return 302 https://newke.com;
15     }
16 
17     location /test2
18     {
19         return 302 https://www.baidu.com;
20     }
21 
22     location /
23     {
24 
25         # 访问 /permanent.html 的时候,页面直接302定向到https://www.baidu.com
26         rewrite /permanent.html https://www.baidu.com redirect;
27 
28         # 把 /html/*.html => /post/*.html ,301定向
29         rewrite ^/html/(.+?).html$ /post/$1.html permanent;
30 
31         # 把 /search/key => /search.html?keyword=key
32         rewrite ^/search/([^/]+?)(/|$) /search.html?keyword=$1 permanent;
33     }
34 }
View Code

nginx中if判断如何使用?

只是上面的简单重写很多时候满足不了需求,比如需要判断当文件不存在时、当路径包含xx时等条件,则需要用到if

Nginx中if语法为:if(condition){…},对给定的条件condition进行判断。如果为真,大括号内命令将被执行

if判断规则
  • 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
  • 直接比较变量和内容时,使用=或!=
  • ~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的正则表达式不匹配,满足条件返回true
  • -f和!-f用来判断是否存在文件
  • -d和!-d用来判断是否存在目录
  • -e和!-e用来判断是否存在文件或目录
  • -x和!-x用来判断文件是否可执行
if使用举例

if条件中一般会使用到一些变量,这些变量有些是用户定义的,有些是系统本身存在的,关于变量相关内容请看下文[Nginx中如何使用变量?]

 1 server {
 2     if ($http_user_agent ~ MSIE) {
 3         rewrite ^(.*)$ /msie/$1 break;
 4     } 
 5     # 如果UA包含"MSIE",rewrite请求到/msid/目录下
 6 
 7     if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
 8         set $id $1;
 9     } 
10     # 如果cookie匹配正则,设置变量$id等于正则引用部分
11 
12     if ($request_method = POST) {
13         return 405;
14     } 
15     # 如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
16 
17     if ($slow) {
18         limit_rate 10k;
19     } 
20     # 限速,$slow可以通过 set 指令设置
21 
22     if (!-f $request_filename){
23         break;
24         proxy_pass  http://127.0.0.1; 
25     } 
26     # 如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
27 
28     if ($args ~ post=140){
29         rewrite ^ http://example.com/ permanent;
30     } 
31     # 如果query string中包含"post=140",永久重定向到example.com
32 
33     location ~* .(gif|jpg|png|swf|flv)$ {
34         valid_referers none blocked www.jefflei.com www.leizhenfang.com;
35         if ($invalid_referer) {
36             return 404;
37         } 
38         # 防盗链
39     }
40 }

nginx变量如何使用?

Nginx也可以使用变量,变量分为系统变量和自定义变量

变量特点
  • Nginx变量的创建只能发生在Nginx配置加载的时候,或者说Nginx启动的时候;
  • Nginx变量的赋值操作则只会发生在请求实际处理的时候;
  • 每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,它们之间的值彼此互不干扰;
自定义变量

自定义变量通过set命令初始化和赋值,变量名前需要加$符号作为区分

1  # 设置变量$a = "helloworld";
2  set $a hello world;
3 
4  # 设置变量$b = "helloworld, helloworld";
5  set $b "$a, $a";
系统变量

Nginx中的系统变量如下:

 1 $args              # 这个变量等于请求行中的参数,同$query_string
 2 $content_length    # 请求头中的Content-length字段。
 3 $content_type      # 请求头中的Content-Type字段。
 4 $document_root     # 当前请求在root指令中指定的值。
 5 $host              # 请求主机头字段,如果不存在则为服务器名称。
 6 $http_user_agent   # 客户端agent信息
 7 $http_cookie       # 客户端cookie信息
 8 $limit_rate        # 这个变量可以限制连接速率。
 9 $request_method    # 客户端请求的动作,通常为GET或POST。
10 $remote_addr       # 客户端的IP地址。
11 $remote_port       # 客户端的端口。
12 $remote_user       # 已经经过Auth Basic Module验证的用户名。
13 $request_filename  # 当前请求的文件路径,由root或alias指令与URI请求生成。
14 $scheme            # HTTP方法(如http,https)。
15 $server_protocol   # 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
16 $server_addr       # 服务器地址,在完成一次系统调用后可以确定这个值。
17 $server_name       # 服务器名称。
18 $server_port       # 请求到达服务器的端口号。
19 $request_uri       # 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
20 $uri               # 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
21 $document_uri      # 与$uri相同。

nginx中一些常用的命令

  • nginx -t 检查配置是否可用
  • nginx -s reload 重启nginx

参考文献

转载:https://blog.csdn.net/zdplife/article/details/79563060

原文地址:https://www.cnblogs.com/qq1069284034/p/9413755.html