Nginx服务器配置里,location的多条件匹配是个非常实用但又有点复杂的知识点,本文会详细介绍在Nginx中实现location多条件匹配的多种方法。

一、Nginx中location指令的基础认知

在Nginx服务器里,location指令的作用是对请求的网址(URI)进行匹配,然后根据匹配的结果来执行相应的操作,比如把请求转发到不同的后端服务器,或者返回特定的页面内容等。不过,location原本是按照单一的匹配规则来工作的,那怎么实现多个条件的匹配呢?下面就来详细讲讲。

二、实现location多条件匹配的多种方式

(一)利用多个location块

Nginx允许我们定义多个location块,每个location块都可以设置不同的匹配条件。当有请求进来时,Nginx会按照优先级来选择最合适的location块进行处理。

server { listen 80; # 匹配 /xianyang/ 路径 location /xianyang/ { proxy_pass http://10.175.12.236:8080; add_header 'Access-Control-Allow-Origin' '*'; } # 匹配 /api/ 路径 location /api/ { proxy_pass http://10.175.12.237:8080; add_header 'Access-Control-Allow-Origin' '*'; } # 默认匹配 location / { root html; index index.html; } } 

这里要注意Nginx的匹配优先级规则:

  • 精确匹配(location = /path)的优先级是最高的。比如location = /specific-url,只有请求的网址完全是/specific-url时才会匹配。
  • 正则表达式匹配(location ~ /path)次之。这种匹配方式更灵活,可以匹配符合特定模式的网址。
  • 前缀匹配(location /path)优先级最低。只要请求网址的开头和配置的路径一致,就会匹配。

(二)运用正则表达式匹配多个条件

要是想在一个location块里匹配多个不同的路径,就可以借助正则表达式。

server { listen 80; # 匹配 /xianyang/ 或 /api/ 路径 location ~ ^/(xianyang|api)/ { proxy_pass http://10.175.12.236:8080; add_header 'Access-Control-Allow-Origin' '*'; } # 默认匹配 location / { root html; index index.html; } } 

这里的~表示开启正则表达式匹配模式,^/(xianyang|api)/的意思是匹配以/xianyang/或者/api/开头的网址路径。

(三)借助map指令动态选择后端

如果需要根据请求的路径或者其他条件来动态地选择后端服务器,map指令就能派上用场啦。

http { # 定义 $backend 变量,根据路径动态选择后端 map $uri $backend { default http://default-backend:8080; "~^/xianyang/" http://10.175.12.236:8080; "~^/api/" http://10.175.12.237:8080; } server { listen 80; location / { proxy_pass $backend; # 使用动态选择的 $backend proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

在这段代码里,map $uri $backend表示根据$uri(也就是请求的路径)的值来动态设置$backend变量。当路径以/xianyang/开头时,$backend就被设置为http://10.175.12.236:8080;以/api/开头时,$backend被设置为http://10.175.12.237:8080;其他情况就使用默认的http://default-backend:8080

(四)使用if条件实现多条件匹配

虽然不太建议过度使用if,但在某些情况下,它也能实现多个条件的匹配。

server { listen 80; location / { # 根据路径动态选择后端 if ($uri ~* "^/xianyang/") { proxy_pass http://10.175.12.236:8080; } if ($uri ~* "^/api/") { proxy_pass http://10.175.12.237:8080; } # 默认后端 if ($uri !~* "^/xianyang/" && $uri !~* "^/api/") { root html; index index.html; } } } 

不过要注意,if的性能不太好,所以尽量别在location里大量使用。而且if条件里不能直接把proxy_pass和其他指令组合使用,得小心操作。

(五)通过try_files实现多条件匹配

要是想根据文件或路径是否存在来选择不同的处理逻辑,try_files就能帮到你。

server { listen 80; location / { # 尝试匹配文件,如果不存在则转发到后端 try_files $uri @backend; } location @backend { # 根据路径选择后端 if ($uri ~* "^/xianyang/") { proxy_pass http://10.175.12.236:8080; } if ($uri ~* "^/api/") { proxy_pass http://10.175.12.237:8080; } # 默认后端 proxy_pass http://default-backend:8080; } } 

try_files $uri @backend的作用是先尝试去匹配文件路径$uri,要是文件不存在,就会跳转到@backend这个命名位置继续处理。

(六)利用include分离多个location配置

当有很多location块需要管理时,可以把它们分别写到单独的文件里,然后用include指令引入。
主配置文件:

server { listen 80; include /etc/nginx/conf.d/*.conf; # 引入所有 .conf 文件 } 

/etc/nginx/conf.d/xianyang.conf

location /xianyang/ { proxy_pass http://10.175.12.236:8080; add_header 'Access-Control-Allow-Origin' '*'; } 

/etc/nginx/conf.d/api.conf

location /api/ { proxy_pass http://10.175.12.237:8080; add_header 'Access-Control-Allow-Origin' '*'; } 

这样做可以让配置文件更模块化,方便管理和维护。

(七)综合示例:多条件匹配

下面是一个综合示例,结合了前缀匹配、正则表达式和默认后端的配置。

server { listen 80; # 精确匹配 /xianyang/ location = /xianyang/ { proxy_pass http://10.175.12.236:8080; add_header 'Access-Control-Allow-Origin' '*'; } # 匹配 /xianyang/ 或 /api/ 路径(正则表达式) location ~ ^/(xianyang|api)/ { proxy_pass http://10.175.12.236:8080; add_header 'Access-Control-Allow-Origin' '*'; } # 默认匹配 location / { root html; index index.html; } } 

三、总结

在Nginx中实现location多条件匹配的方法各有特点:

  • 多个location块:适合条件简单的匹配场景,Nginx会按照优先级自动选择最合适的块。
  • 正则表达式:在需要匹配多个不同路径时非常好用。
  • map指令:特别适合根据条件动态选择后端服务器的情况。
  • if条件:能实现复杂的逻辑,但性能不太好,使用时要谨慎。
  • try_files:根据文件或路径是否存在来选择处理逻辑很方便。
  • include:可以让配置文件更模块化,便于管理和维护。

大家在实际使用时,可以根据具体的需求来选择最合适的方法。要是逻辑比较复杂,一般推荐使用map指令或者正则表达式来实现多条件匹配。