Nginx 的 location 匹配规则和优先级是怎样的?
简化版
Nginx 的 location 用来匹配请求 URL 并决定如何处理。匹配修饰符及优先级从高到低:① =(精确匹配)——URL 完全相等,优先级最高,匹配上立即停止;② ^~(前缀匹配,不再查正则)——匹配前缀且匹配后不再找正则;③ ~ / ~*(正则匹配,区分/不区分大小写)——按配置文件中出现顺序匹配,命中第一个就停;④ 普通前缀匹配(无修饰符)——记录最长前缀但会继续找正则。总规则:精确 = > ^~ 前缀 > 正则 ~ > 普通前缀,正则和普通前缀之间正则优先。
详细版
修饰符与优先级:
| 修饰符 | 类型 | 优先级 | 说明 |
|---|---|---|---|
= | 精确匹配 | 1(最高) | URL 完全相等,命中立即停止 |
^~ | 前缀匹配 | 2 | 匹配前缀,命中后不再匹配正则 |
~ | 正则(区分大小写) | 3 | 按出现顺序,命中第一个即停 |
~* | 正则(不区分大小写) | 3 | 同上,不区分大小写 |
| (无) | 普通前缀 | 4(最低) | 记录最长前缀,但会继续找正则 |
匹配流程:
- 先找精确匹配
=,命中直接用。 - 再找普通前缀匹配,记住匹配最长的那个;如果它带
^~,直接用、不再找正则。 - 然后按顺序匹配正则
~/~*,命中第一个就用。 - 如果正则都没命中,用第 2 步记住的最长前缀匹配。
location = /exact { } # 只匹配 /exact
location ^~ /static/ { } # 匹配 /static/ 开头,且不再找正则
location ~ \.php$ { } # 匹配 .php 结尾(区分大小写)
location ~* \.(jpg|png)$ { } # 匹配图片(不区分大小写)
location / { } # 兜底,匹配所有
完整版教学
一、location 的作用
location 是 Nginx 配置里最核心的指令之一,用于根据请求的 URI 路径,匹配不同的处理规则——不同路径可以走不同的后端、返回不同的静态目录、应用不同的限流/缓存策略。一个 server 块里通常有多个 location,Nginx 需要一套明确的规则来决定「一个请求 URL 到底匹配哪个 location」——这就是匹配规则和优先级。
二、五种匹配修饰符
location 后面可以跟不同的修饰符,决定匹配方式:
=精确匹配:URL 必须完全等于给定路径才匹配。如location = /login只匹配/login,不匹配/login/或/login/x。^~前缀匹配(特殊):匹配以给定字符串开头的 URL,且一旦匹配上,就不再去匹配正则(这是它和普通前缀的关键区别)。~正则匹配(区分大小写):用正则表达式匹配,~ \.php$匹配所有.php结尾的。~*正则匹配(不区分大小写):同上但忽略大小写,~* \.jpg$匹配.jpg、.JPG。- 无修饰符(普通前缀匹配):匹配以给定字符串开头的 URL,但会继续找正则(正则优先级更高)。
三、匹配优先级与完整流程
这是最容易考、也最容易记混的地方。Nginx 匹配一个请求 URL 的完整流程是:
- 先检查精确匹配
=:如果有 location 用=且完全匹配,立即选它,结束。优先级最高。 - 再检查所有前缀匹配(普通前缀和
^~),找出匹配长度最长的那一个,先记住它:- 如果这个最长前缀匹配是带
^~的,直接使用它,不再匹配正则,结束。 - 如果是普通前缀(无修饰符),先记住,但继续往下匹配正则。
- 如果这个最长前缀匹配是带
- 按配置文件中的书写顺序,依次检查正则
~/~*:命中第一个正则就使用它,结束(正则之间是「顺序优先」,不是「最长优先」)。 - 如果所有正则都没命中,就使用第 2 步记住的最长普通前缀匹配。
总优先级:= 精确 > ^~ 前缀 > 正则 ~/~* > 普通前缀。关键记忆点:普通前缀匹配「最长优先」,正则匹配「顺序优先(第一个命中)」,正则优先级高于普通前缀但低于 ^~。
四、为什么 ^~ 常用于静态资源
^~ 的「匹配上就不再找正则」特性有个重要用途:保护静态资源路径不被正则规则拦截。
例如你有一个正则 location ~* \.(jpg|png|css|js)$ { } 处理所有静态文件,但又想让 /static/ 目录下的所有请求走一个特定处理(比如直接返回、加长缓存),且不希望它们再被上面那个正则规则匹配。这时用 location ^~ /static/ { }:请求 /static/a.jpg 会被 ^~ /static/ 命中并直接使用,不会再去匹配 ~* \.jpg$ 那个正则。用 ^~ 就能「短路」正则匹配。
五、常见配置示例解读
location = / { } # 只匹配首页 /(精确)
location = /favicon.ico { } # 精确匹配 favicon,避免走别的规则
location ^~ /static/ { } # /static/ 开头的静态资源,短路正则
location ~* \.(gif|jpg|png)$ { } # 图片(不区分大小写正则)
location ~ \.php$ { } # PHP 请求转发给 FastCGI
location / { } # 兜底,匹配所有其他请求
一个请求 /static/logo.png:会先被 ^~ /static/ 命中(前缀且不再找正则),而不会走 ~* \.png$。一个请求 /user/avatar.jpg:/static/ 不匹配,走正则 ~* \.jpg$。一个请求 /api/users:正则都不中,走兜底 location /。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| 精确匹配 | location = /x 优先级最高 |
| 前缀匹配 | 普通前缀和 ^~ 前缀 |
| 正则匹配 | ~ 区分大小写,~* 不区分大小写 |
location = /api/user {}
location ^~ /static/ {}
location ~* \.jpg$ {}
location / {}
order: exact -> ^~ prefix -> regex -> longest prefix
location 不是从上到下简单匹配;精确、^~、正则、最长前缀有固定优先级。
- 误区:Nginx location 按配置顺序第一个命中。 普通 location 有优先级规则,不是简单从上往下。
- 误区:最长前缀一定赢过正则。 普通最长前缀会暂存,随后正则仍可能覆盖;
^~才会阻止正则检查。 - 误区:
/api和/api/完全一样。 前缀边界不同,可能匹配到/apix等意外路径,要谨慎写。 - 追问:
=适合什么? 适合首页、健康检查等固定路径,命中后不再继续匹配。 - 追问:
^~适合什么? 适合静态资源目录等明确前缀,避免被后续正则抢走。 - 追问:如何排查 location 命中? 简化配置、加返回标识、看 access log,并用 nginx -T 查看最终配置。
七、加强记忆
Nginx location 匹配优先级从高到低:= 精确匹配(完全相等,命中立即停)> ^~ 前缀匹配(命中后不再找正则)> ~/~* 正则匹配(区分/不区分大小写,按书写顺序命中第一个即停)> 普通前缀匹配(最长优先,但会继续找正则)。匹配流程:先 = → 再找最长前缀(若带 ^~ 直接用、否则记住 → 按顺序找正则命中即用 → 正则都不中才用记住的最长前缀)。关键点:普通前缀「最长优先」、正则「顺序优先」、^~ 能短路正则(常用于静态资源目录)。口诀:精确 > ^~ > 正则 > 普通前缀;前缀比长度、正则比顺序。