• 你需要知道的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

  • 相关阅读:
    Ubuntu(Debian)的aptitude与aptget的区别和联系
    安装lxml相关
    解决Ubuntu 12.04更新后 ”系统的网络服务与此版本的网络管理器不兼容“问题
    Windows下配置Nginx代理Django
    scons入门笔记
    git仓库合并(向原有git仓库中加入新仓库)
    asterisk源码分析(main函数)
    live555源码编译(win7+vs2010)
    asterisk源码目录结构
    小试一题
  • 原文地址:https://www.cnblogs.com/qq1069284034/p/9413755.html
Copyright © 2020-2023  润新知