Nginx location 匹配规则教程:=、~、^~ 优先级原理与配置实操及常见问题

一、适用场景:location 写错会出什么问题

location 是 Nginx 配置里使用频率最高的指令之一,几乎所有网站都离不开它:静态资源缓存、动静分离、反向代理、PHP 解析、伪静态规则,本质上都是通过 location 把不同请求分流到不同的处理逻辑。对站长和运维来说,location 写错是最常见、也最容易被忽视的故障来源。

比如想给图片目录加缓存,却把整个站点都缓存了;想反向代理 /api/ 给后端服务,请求却走到了静态文件;或者明明写了一条 .php 结尾的正则,PHP 文件却变成下载而不是执行。这些问题不报错、不崩溃,只是"行为不对",排查起来反而更花时间。搞清楚 location 的匹配规则,是配置 Nginx 的基本功。

本文以一台已经装好 Nginx 的 Linux 服务器为例(宝塔面板用户在软件商店安装 Nginx 后同样适用),完整讲解 location 的四种匹配方式、优先级规则、动静分离配置实操和常见错误排查,适合站长、开发和运维人员直接照着操作。

二、location 的四种匹配方式与写法

location 块定义在 server 块内部,写法是在 location 后面跟上匹配模式,再用大括号包裹要执行的指令。Nginx 支持四种匹配方式:精确匹配、普通前缀匹配、跳过正则的前缀匹配和正则匹配,此外还有一种用于内部跳转的命名 location。

精确匹配使用等号,只有请求 URI 完全一致时才命中,例如 location = /login 只匹配 /login 这一个地址,/login/ 或 /login.html 都不会命中。普通前缀匹配不加符号,如 location /static/ 匹配所有以 /static/ 开头的请求。^~ 前缀匹配在前缀命中的前提下,告诉 Nginx 不要再检查正则 location。正则匹配用 ~(区分大小写)和 ~*(不区分大小写),可以匹配 .php、.jpg 这类有规律的结尾。

命名 location 以 @ 开头,只能被 try_files 或 error_page 内部跳转,不能直接匹配用户请求,一般用于统一错误页或重写后的兜底处理。四种写法的示例如下:

# 精确匹配:只匹配 /login
location = /login {
    return 200 "exact match";
}

# 前缀匹配:匹配所有 /static/ 开头的请求
location ^~ /static/ {
    expires 30d;
}

# 正则匹配:区分大小写,匹配 .php 结尾
location ~ \.php$ {
    fastcgi_pass unix:/tmp/php-cgi-74.sock;
}

# 正则匹配:不区分大小写,匹配常见图片和静态后缀
location ~* \.(gif|jpg|jpeg|png|css|js)$ {
    expires 7d;
}

# 普通前缀匹配:兜底
location / {
    try_files $uri $uri/ /index.php?$args;
}

需要特别注意的是,正则表达式里的特殊字符(如 .)建议转义,否则 . 会匹配任意字符,可能造成意料之外的命中。

三、匹配优先级:Nginx 到底先匹配哪一个

多种匹配方式同时存在时,Nginx 并不是按配置文件里的书写顺序从上到下判断,而是遵循一套固定规则。完整规则可以分五步理解:

第一步,Nginx 先检查精确匹配(=),一旦命中立即停止,后面的规则全部不再检查。第二步,在普通前缀匹配和 ^~ 前缀匹配中找出最长的那一个,先记录下来,但不立即使用。第三步,如果这个最长前缀匹配是 ^~ 形式,就直接使用它,不再检查任何正则 location。第四步,如果最长前缀是普通前缀,则按照配置文件中出现的顺序逐条检查正则 location,第一条匹配上的正则生效,后面的正则即使更"精确"也不会生效。第五步,如果所有正则都没有匹配上,就使用第二步记录下来的最长前缀匹配。

举个例子:假设请求地址是 /static/logo.png,配置里同时有 location ^~ /static/ 和 location ~* \.(png|jpg)$,由于最长前缀命中且是 ^~ 形式,Nginx 直接使用前者,正则被跳过。再假设请求是 /upload/a.PNG,只有 location ~ \.png$(区分大小写)和 location /,此时正则区分大小写,.PNG 不会被命中,最终落到 location / 兜底。把大小写不敏感的场景换成 ~*,结果就完全不同。

记住一句话:精确匹配优先,其次是最长前缀,正则按书写顺序取第一个。实际配置中绝大多数"奇怪行为",都可以用这条规则解释清楚。

Nginx location 匹配规则配置:数据中心网络设备与服务器运维场景
Nginx location 匹配规则:精确匹配、前缀匹配与正则匹配的优先级配置实操

四、实操步骤:配置动静分离 location

下面以一个典型场景演示完整操作:让 /static/ 目录走本地静态文件并加缓存,让 /api/ 请求转发给本机 3000 端口的后端服务,其余请求按伪静态规则处理。涉及修改 Nginx 配置和重载服务,操作前一定要备份,并在业务低峰期进行。

第一步,备份现有配置文件。Nginx 主配置和站点配置一般在 /etc/nginx/ 目录下,宝塔面板的站点配置文件通常在 /www/server/panel/vhost/nginx/ 目录。先用 cp 复制一份带日期的备份,改坏了可以随时恢复:

cp /www/server/panel/vhost/nginx/example.com.conf \
   /www/server/panel/vhost/nginx/example.com.conf.bak.20261110

第二步,编辑站点配置文件,在 server 块内加入以下 location 规则(按你的实际路径和端口调整):

server {
    listen 80;
    server_name example.com;
    root /www/wwwroot/example.com;
    index index.php index.html;

    # 静态目录:前缀命中后跳过正则,直接加缓存头
    location ^~ /static/ {
        expires 30d;
        access_log off;
    }

    # 接口请求:转发给本机后端服务
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # PHP 解析
    location ~ \.php$ {
        fastcgi_pass unix:/tmp/php-cgi-74.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # 伪静态兜底
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}

第三步,测试配置语法。Nginx 提供了 -t 参数做干跑检查,语法错误时会提示具体行号,不会影响正在运行的服务:

nginx -t

第四步,平滑重载配置。确认测试通过后使用 reload 而不是 restart,reload 不会中断已经建立的连接:

nginx -s reload

第五步,验证效果。用 curl 检查静态资源和接口的响应,静态目录应能看到 Cache-Control 缓存头,/api/ 请求应返回后端服务的内容:

curl -I http://example.com/static/logo.png
curl -I http://example.com/api/status

如果 reload 后网站异常,先用备份文件恢复配置再重载,排查清楚原因后再重新修改。

五、常见配置错误与排查

错误一:新加的 location 反而 404。先检查 root 指向的目录是否正确,再确认是否漏掉了 try_files 或 index 指令。前缀命中的 location 会继承 server 块的 root,但如果路径写错,Nginx 只会在错误的目录里找文件。

错误二:正则 location 不生效。最常见原因是前面存在 ^~ 前缀匹配,正则被整体跳过;另一种情况是另一条正则出现在更前面,先命中生效。调整顺序或改用 ^~ 前缀即可定位。

错误三:proxy_pass 的转发地址不对。proxy_pass 后面带不带 URI 斜杠,转发时的路径拼装方式不同,容易把 /api/user 变成 /user 或出现双斜杠,具体见下面 FAQ。

错误四:大小写问题。~ 区分大小写,~* 不区分。上传的图片可能是 .JPG 后缀,用 ~ \.(jpg|png)$ 就匹配不到,换成 ~* 更稳妥。

六、常见问题与总结

问题一:精确匹配和前缀匹配有什么区别,什么场景用哪个?精确匹配(=)只命中完全相同的 URI,性能最好,适合 /login、/health 这类固定地址;前缀匹配覆盖一整段路径,适合目录、接口前缀等批量场景。两者可以组合使用,精确的写在前面更直观。

问题二:多个正则 location 都能匹配时,到底谁生效?按配置文件中出现的顺序,第一个匹配的生效,与"哪个正则更精确"无关。如果希望某条正则优先生效,就把它写到前面。

问题三:proxy_pass 加斜杠和不加斜杠有什么区别?proxy_pass 后面带 URI(如 http://127.0.0.1:3000/)时,Nginx 会把 location 匹配到的那段路径替换成 proxy_pass 的 URI,location /api/ 配合 proxy_pass http://127.0.0.1:3000/ 会把 /api/user 转成 /user;不带 URI(如 http://127.0.0.1:3000)时,原始请求地址原样转发,/api/user 仍然是 /api/user。配置后端的接口前缀时要特别留意这一点。

问题四:修改 location 配置后需要重启 Nginx 吗?不需要重启,nginx -t 测试通过后执行 nginx -s reload 即可平滑生效。重启会造成连接中断,线上服务应尽量避免。

总结:location 匹配规则的核心是"精确匹配优先、最长前缀其次、正则按顺序取第一个",^~ 是打断正则的开关。修改任何 Nginx 配置前养成备份习惯,用 nginx -t 验证、用 reload 生效,再配合 curl 检查实际行为,绝大多数分流问题都能快速定位。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容