Skip to content

nginx 配置总结

nginx 介绍

nginx 是一个高性能的 web 服务器,常用作反向代理服务器。nginx 作为反向代理服务器,就是把 http 请求转发到另一个或者一些服务器上。 通过把本地一个 url 前缀映射到要跨域访问的 web 服务器上,就可以实现跨域访问。 对于浏览器来说,访问的就是同源服务器上的一个 url。而 nginx 通过检测 url 前缀,把 http 请求转发到后面真实的物理服务器。并通过 rewrite 命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的。 简单说,nginx 服务器欺骗了浏览器,让它认为这是同源调用,从而解决了浏览器的跨域问题。又通过重写 url,欺骗了真实的服务器,让它以为这个 http 请求是直接来自与用户浏览器的。 这样,为了解决跨域问题,只需要动一下 nginx 配置文件即可。简单、强大、高效!

nginx.conf 配置文件

Nginx 配置文件主要分成四部分:main(全局设置)server(主机设置)upstream(上游服务器设置,主要为反向代理、负载均衡相关配置)location(URL 匹配特定位置后的设置),每部分包含若干个指令。

main 部分设置的指令将影响其它所有部分的设置;server部分的指令主要用于指定虚拟主机域名、IP 和端口;upstream 的指令用于设置一系列的后端服务器,设置反向代理及后端服务器的负载均衡;location 部分用于匹配网页位置(比如,根目录“/”,“/images”,等等)。

他们之间的关系是:server 继承 mainlocation 继承 serverupstream 既不会继承指令也不会被继承。它有自己的特殊指令,不需要在其他地方的应用。

通用

下面的 nginx.conf 简单的实现 nginx 在前端做反向代理服务器的例子,处理 js、png 等静态文件,jsp 等动态请求转发到其它服务器 tomcat

config
user  www www;
worker_processes  2;

error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        logs/nginx.pid;


events {
    use epoll;
    worker_connections  2048;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    # tcp_nopush     on;

    keepalive_timeout  65;

  # gzip压缩功能设置
    gzip on;
    gzip_min_length 1k;
    gzip_buffers    4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 6;
    gzip_types text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
    gzip_vary on;

  # http_proxy 设置
    client_max_body_size   10m;
    client_body_buffer_size   128k;
    proxy_connect_timeout   75;
    proxy_send_timeout   75;
    proxy_read_timeout   75;
    proxy_buffer_size   4k;
    proxy_buffers   4 32k;
    proxy_busy_buffers_size   64k;
    proxy_temp_file_write_size  64k;
    proxy_temp_path   /usr/local/nginx/proxy_temp 1 2;

  # 设定负载均衡后台服务器列表
    upstream  backend  {
              #ip_hash;
              server   192.168.10.100:8080 max_fails=2 fail_timeout=30s ;
              server   192.168.10.101:8080 max_fails=2 fail_timeout=30s ;
    }

  # 很重要的虚拟主机配置
    server {
        listen       80;
        server_name  itoatest.example.com;
        root   /apps/oaapp;

        charset utf-8;
        access_log  logs/host.access.log  main;

        #对 / 所有做负载均衡+反向代理
        location / {
            root   /apps/oaapp;
            index  index.jsp index.html index.htm;

            proxy_pass        http://backend;
            proxy_redirect off;
            # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header  Host  $host;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

        }

        #静态文件,nginx自己处理,不去backend请求tomcat
        location  ~* /download/ {
            root /apps/oa/fs;

        }
        location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
        {
            root /apps/oaapp;
            expires      7d;
        }
        location /nginx_status {
            stub_status on;
            access_log off;
            allow 192.168.10.0/24;
            deny all;
        }

        location ~ ^/(WEB-INF)/ {
            deny all;
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

  ## 其它虚拟主机,server 指令开始
}

常用指令说明

main 全局配置

nginx 在运行时与具体业务功能(比如 http 服务或者 email 服务代理)无关的一些参数,比如工作进程数,运行的身份等。

  • woker_processes 2

    在配置文件的顶级 main 部分,worker 角色的工作进程的个数,master 进程是接收并分配请求给 worker 处理。这个数值简单一点可以设置为 cpu 的核数 grep ^processor /proc/cpuinfo | wc -l,也是 auto 值,如果开启了 sslgzip 更应该设置成与逻辑 CPU 数量一样甚至为 2 倍,可以减少 I/O 操作。如果 nginx 服务器还有其它服务,可以考虑适当减少。

  • worker_cpu_affinity

    也是写在 main 部分。在高并发情况下,通过设置 cpu 粘性来降低由于多 CPU 核切换造成的寄存器等现场重建带来的性能损耗。如 worker_cpu_affinity 0001 0010 0100 1000; (四核)。

  • worker_connections 2048

    写在 events 部分。每一个 worker 进程能并发处理(发起)的最大连接数(包含与客户端或后端被代理服务器间等所有连接数)。nginx 作为反向代理服务器,计算公式 最大连接数 = worker_processes \* worker_connections/4,所以这里客户端最大连接数是 1024,这个可以增到到 8192 都没关系,看情况而定,但不能超过后面的 worker_rlimit_nofile。当 nginx 作为 http 服务器时,计算公式里面是除以 2。

  • worker_rlimit_nofile 10240

    写在 main 部分。默认是没有设置,可以限制为操作系统最大的限制 65535。

  • use epoll

    写在 events 部分。在 Linux 操作系统下,nginx 默认使用 epoll 事件模型,得益于此,nginxLinux 操作系统下效率相当高。同时 NginxOpenBSDFreeBSD 操作系统上采用类似于 epoll 的高效事件模型 kqueue。在操作系统不支持这些高效模型时才使用 select

http 服务器

与提供 http 服务相关的一些配置参数。例如:是否使用 keepalive 啊,是否使用 gzip 进行压缩等。

  • sendfile on

    开启高效文件传输模式,sendfile 指令指定 nginx 是否调用 sendfile 函数来输出文件,减少用户空间到内核空间的上下文切换。对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载。

  • keepalive_timeout 65

    长连接超时时间,单位是秒,这个参数很敏感,涉及浏览器的种类、后端服务器的超时设置、操作系统的设置,可以另外起一片文章了。长连接请求大量小文件的时候,可以减少重建连接的开销,但假如有大文件上传,65s 内没上传完成会导致失败。如果设置时间过长,用户又多,长时间保持连接会占用大量资源。

  • send_timeout

    用于指定响应客户端的超时时间。这个超时仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx 将会关闭连接。

  • client_max_body_size 10m

    允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值

  • client_body_buffer_size 128k

    缓冲区代理缓冲用户端请求的最大字节数

模块 http_proxy

这个模块实现的是 nginx 作为反向代理服务器的功能,包括缓存功能(另见文章)

  • proxy_connect_timeout 60

    nginx 跟后端服务器连接超时时间(代理连接超时)

  • proxy_read_timeout 60

    连接成功后,与后端服务器两个成功的响应操作之间超时时间(代理接收超时)

  • proxy_buffer_size 4k

    设置代理服务器(nginx)从后端 realserver 读取并保存用户头信息的缓冲区大小,默认与 proxy_buffers 大小相同,其实可以将这个指令值设的小一点

  • proxy_buffers 4 32k

    proxy_buffers 缓冲区,nginx 针对单个连接缓存来自后端 realserver 的响应,网页平均在 32k 以下的话,这样设置

  • proxy_busy_buffers_size 64k

    高负荷下缓冲大小(proxy_buffers*2)

  • proxy_max_temp_file_size

    当 proxy_buffers 放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认 1024M,它与 proxy_cache 没有关系。大于这个值,将从 upstream 服务器传回。设置为 0 禁用。

  • proxy_temp_file_write_size 64k

    当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。proxy_temp_path(可以在编译的时候)指定写到哪那个目录。

模块 http_gzip
  • gzip on : 开启 gzip 压缩输出,减少网络传输。

    • gzip_min_length 1k : 设置允许压缩的页面最小字节数,页面字节数从 header 头得 content-length 中进行获取。默认值是 20。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大。
    • gzip_buffers 4 16k : 设置系统获取几个单位的缓存用于存储 gzip 的压缩结果数据流。4 16k 代表以 16k 为单位,安装原始数据大小以 16k 为单位的 4 倍申请内存。
    • gzip_http_version 1.0 : 用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了 Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.0,故请设置为 1.0。
    • gzip_comp_level 6 : gzip 压缩比,1 压缩比最小处理速度最快,9 压缩比最大但处理速度最慢(传输快但比较消耗 cpu)
    • gzip_types :匹配 mime 类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。
    • gzip_proxied any : Nginx 作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header 头。
    • gzip_vary on : 和 http 头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过 gzip 压缩的页面,例如,用 Squid 缓存经过 Nginx 压缩的数据。。

server 虚拟主机

http 服务上支持若干虚拟主机。每个虚拟主机一个对应的 server 配置项,配置项里面包含该虚拟主机相关的配置。在提供 mail 服务的代理时,也可以建立若干 server。每个 server 通过监听地址或端口来区分。

  • listen:监听端口,默认 80,小于 1024 的要以 root 启动。可以为 listen *:80、listen 127.0.0.1:80 等形式。
  • server_name:服务器名,如 localhost、www.example.com,可以通过正则匹配。
模块 http_stream

这个模块通过一个简单的调度算法来实现客户端 IP 到后端服务器的负载均衡,upstream 后接负载均衡器的名字,后端 realserver 以 host:port options; 方式组织在 {} 中。如果后端被代理的只有一台,也可以直接写在 proxy_pass 。

location

http 服务中,某些特定的 URL 对应的一系列配置项。

  • root /var/www/html

    定义服务器的默认网站根目录位置。如果 locationURL 匹配的是子目录或文件,root 没什么作用,一般放在 server 指令里面或/下。

  • index.jsp index.html index.htm

    定义路径下默认访问的文件名,一般跟着 root 放

  • proxy_pass http:/backend

    请求转向 backend 定义的服务器列表,即反向代理,对应 upstream 负载均衡器。也可以 proxy_pass http://ip:port

  • proxy_redirect off;

    proxy_set_header Host \$host;

    proxy_set_header X-Real-IP \$remote_addr;

    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;

    这四个暂且这样设,如果深究的话,每一个都涉及到很复杂的内容,也将通过另一篇文章来解读。

其他

访问控制 allow/deny

Nginx 的访问控制模块默认就会安装,而且写法也非常简单,可以分别有多个 allow,deny,允许或禁止某个 ip 或 ip 段访问,依次满足任何一个规则就停止往下匹配。如:

config
location /nginx-status {
  stub_status on;
  access_log off;
#  auth_basic   "NginxStatus";
#  auth_basic_user_file   /usr/local/nginx-1.6/htpasswd;

  allow 192.168.10.100;
  allow 172.29.73.0/24;
  deny all;
}

我们也常用 httpd-devel 工具的 htpasswd 来为访问的路径设置登录密码:

config
# htpasswd -c htpasswd admin
New passwd:
Re-type new password:
Adding password for user admin

# htpasswd htpasswd admin    //修改admin密码
# htpasswd htpasswd sean    //多添加一个认证用户

这样就生成了默认使用 CRYPT 加密的密码文件。打开上面 nginx-status 的两行注释,重启 nginx 生效。

列出目录 autoindex

Nginx 默认是不允许列出整个目录的。如需此功能,打开 nginx.conf 文件,在 location,server 或 http 段中加入 autoindex on;,另外两个参数最好也加上去:

  • autoindex_exact_size off;

    默认为 on,显示出文件的确切大小,单位是 bytes。改为 off 后,显示出文件的大概大小,单位是 kB 或者 MB 或者 GB

  • autoindex_localtime on;

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

config
location /images {
  root   /var/www/nginx-default/images;
  autoindex on;
  autoindex_exact_size off;
  autoindex_localtime on;
  }

重新加载 nginx 配置文件

bash
    nginx -s reload

location 正则写法

config
location  = / {
  # 精确匹配 / ,主机名后面不能带任何字符串
  [ configuration A ]
}

location  / {
  # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
  # 但是正则和最长字符串会优先匹配
  [ configuration B ]
}

location /documents/ {
  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration C ]
}

location ~ /documents/Abc {
  # 匹配任何以 /documents/Abc 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration CC ]
}

location ^~ /images/ {
  # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
  [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
  # 匹配所有以 gif,jpg或jpeg 结尾的请求
  # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
  [ configuration E ]
}

location /images/ {
  # 字符匹配到 /images/,继续往下,会发现 ^~ 存在
  [ configuration F ]
}

location /images/abc {
  # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
  # F与G的放置顺序是没有关系的
  [ configuration G ]
}

location ~ /images/abc/ {
  # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
    [ configuration H ]
}

location ~* /js/.*/\.js
  • =开头表示精确匹配
  • A中只匹配根目录结尾的请求,后面不能带任何字符串。
  • ^~开头表示uri以某个常规字符串开头,不是正则匹配
  • ~开头表示区分大小写的正则匹配;
  • ~\*开头表示不区分大小写的正则匹配
  • /通用匹配, 如果没有其它匹配,任何请求都会匹配到
  • 顺序(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

按照上面的 location 写法,以下的匹配示例成立:

  • / -> config A 精确完全匹配,即使/index.html 也匹配不了
  • /downloads/download.html -> config B 匹配 B 以后,往下没有任何匹配,采用 B
  • /images/1.gif -> configuration D 匹配到 F,往下匹配到 D,停止往下
  • /images/abc/def -> config D 最长匹配到 G,往下匹配 D,停止往下 你可以看到 任何以/images/开头的都会匹配到 D 并停止,FG 写在这里是没有任何意义的,H 是永远轮不到的,这里只是为了说明匹配顺序
  • /documents/document.html -> config C 匹配到 C,往下没有任何匹配,采用 C
  • /documents/1.jpg -> configuration E 匹配到 C,往下正则匹配到 E
  • /documents/Abc.jpg -> config CC 最长匹配到 C,往下正则顺序匹配到 CC,不会往下到 E

实际使用建议

config
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
    proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
    root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
    proxy_pass http://tomcat:8080/
}

Rewrite 规则

rewrite使用nginx提供的全局变量或自己设置的变量,结合正则表达式标志位实现 url 重写以及重定向。

rewrite 只能放在 server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php 重写。

如果相对域名或参数字符串起作用,可以使用全局变量匹配,也可以使用 proxy_pass 反向代理。

表明看 rewritelocation 功能有点像,都能实现跳转,主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,可以 proxy_pass 到其他机器。很多情况下 rewrite 也会写在 location 里,它们的执行顺序是:

  • 执行 server 块的 rewrite 指令
  • 执行 location 匹配
  • 执行选定的 location 中的 rewrite 指令

如果其中某步 URI 被重写,则重新循环执行 1-3,直到找到真实存在的文件;循环超过 10 次,则返回 500 Internal Server Error 错误。

flag 标志位

  • last : 相当于 Apache 的[L]标记,表示完成 rewrite
  • break : 停止执行当前虚拟主机的后续 rewrite 指令集
  • redirect : 返回 302 临时重定向,地址栏会显示跳转后的地址
  • permanent : 返回 301 永久重定向,地址栏会显示跳转后的地址

因为 301 和 302 不能简单的只返回状态码,还必须有重定向的 URL,这就是 return 指令无法返回 301,302 的原因了。这里 last 和 break 区别有点难以理解:

  • last 一般写在 server 和 if 中,而 break 一般使用在 location 中
  • last 不终止重写后的 url 匹配,即新的 url 会再从 server 走一遍匹配流程,而 break 终止重写后的匹配
  • break 和 last 都能阻止继续执行后面的 rewrite 指令

if 指令与全局变量

if 判断指令

语法为 if(condition){...},对给定的条件 condition 进行判断。如果为真,大括号内的 rewrite 指令将被执行,if 条件(conditon)可以是如下任何内容:

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

例如:

config
if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msid/目录下

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
 } //如果cookie匹配正则,设置变量$id等于正则引用部分

if ($request_method = POST) {
    return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302

if ($slow) {
    limit_rate 10k;
} //限速,$slow可以通过 set 指令设置

if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查

if ($args ~ post=140){
    rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com

location ~* \.(gif|jpg|png|swf|flv)$ {
    valid_referers none blocked www.jefflei.com www.leizhenfang.com;
    if ($invalid_referer) {
        return 404;
    } //防盗链
}

全局变量

下面是可以用作 if 判断的全局变量:

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

例:http://localhost:88/test1/test2/test.php

  • $hostlocalhost
  • $server_port88
  • $request_urihttp://localhost:88/test1/test2/test.php
  • $document_uri/test1/test2/test.php
  • $document_root/var/www/html
  • $request_filename/var/www/html/test1/test2/test.php

rewrite 实例

例 1:

config
http { # 定义 image 日志格式
log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status; # 开启重写日志
rewrite_log on;

    server {
        root /home/www;

        location / {
                # 重写规则信息
                error_log logs/rewrite.log notice;
                # 注意这里要用‘’单引号引起来,避免{}
                rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;
                # 注意不能在上面这条规则后面加上“last”参数,否则下面的set指令不会执行
                set $image_file $3;
                set $image_type $4;
        }

        location /data {
                # 指定针对图片的日志格式,来分析图片类型和大小
                access_log logs/images.log mian;
                root /data/images;
                # 应用前面定义的变量。判断首先文件在不在,不在再判断目录在不在,如果还不在就跳转到最后一个url里
                try_files /$arg_file /image404.html;
        }
        location = /image404.html {
                # 图片不存在返回特定的信息
                return 404 "image not found\n";
        }

}

对形如/images/ef/uh7b3/test.png 的请求,重写到/data?file=test.png,于是匹配到 location /data,先看/data/images/test.png 文件存不存在,如果存在则正常响应,如果不存在则重写 tryfiles 到新的 image404 location,直接返回 404 状态码。

例 2:

config
rewrite ^/images/(.\*)\_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=\$3? last;

对形如/images/bla_500x400.jpg 的文件请求,重写到/resizer/bla.jpg?width=500&height=400 地址,并会继续尝试匹配 location

其他参考:Nginx 极简教程