Nginx Location 块详解:路由 Web 流量
Nginx 以其作为 Web 服务器、反向代理和负载均衡器的速度和灵活性而闻名。实现对请求处理的精确控制的核心机制是 location 块。掌握 location 块对于任何希望优化性能、管理各种应用端点并保护特定资源的管理员来说都至关重要。
本指南全面介绍了 Nginx location 块,解释了不同的匹配修饰符、关键的处理顺序,并提供了有效路由 Web 流量的实用示例。
Location 块的作用和结构
一个 location 块定义了 Nginx 应如何根据请求 URI(统一资源标识符)来响应请求。这些块始终嵌套在 server 块内。
当客户端发起请求(例如,GET /images/logo.png)时,Nginx 会将请求 URI 与监听 server 块中所有定义的 location 块进行比对,以确定适当的处理方式,例如提供文件、重定向客户端或将请求代理到应用服务器。
基本语法
该语法要求一个修饰符(或无修饰符),后跟一个模式(URI):
location [modifier] [pattern] {
# 配置指令 (例如, root, index, proxy_pass)
}
理解 Location 匹配类型(修饰符)
Nginx 提供了五种定义模式匹配的主要方式。修饰符的选择会极大地影响性能和路由精度。
1. 前缀匹配(无修饰符)
这是默认的匹配类型。Nginx 搜索匹配请求 URI 的最长起始字符串。
| 修饰符 | 示例 | 行为 | 最佳使用场景 |
|---|---|---|---|
| (无) | location /blog/ |
匹配以 /blog/ 开头的 URI (例如, /blog/post/1)。 |
通用目的,定义网站的大部分区域。 |
示例:
location /docs/ {
root /var/www/html/public;
# 如果 URI 是 /docs/manual.pdf, Nginx 将查找 /var/www/html/public/docs/manual.pdf
}
2. 精确匹配 (=)
此修饰符强制 URI 与模式之间进行精确匹配。如果匹配成功,Nginx 会立即停止搜索其他 location。这是最快的匹配类型。
| 修饰符 | 示例 | 行为 | 最佳使用场景 |
|---|---|---|---|
= |
location = /favicon.ico |
仅精确匹配 URI /favicon.ico。 |
处理特定的、频繁请求的文件或默认页面。 |
3. 最长前缀,非正则 (^~)
这是一种特殊的前缀匹配。如果 Nginx 使用 ^~ 找到了最长的前缀匹配,它将 立即停止 检查任何正则表达式 (regex) location 块,从而有效地覆盖它们。
| 修饰符 | 示例 | 行为 | 最佳使用场景 |
|---|---|---|---|
^~ |
location ^~ /assets/ |
匹配以 /assets/ 开头的 URI,并阻止检查较慢的正则匹配。 |
快速提供静态资源,确保资源目录被可预测地处理。 |
4. 区分大小写的正则表达式 (~)
这使用 Perl 兼容正则表达式 (PCRE) 进行匹配。它功能强大,但比前缀匹配慢。第一个匹配的正则块获胜。
| 修饰符 | 示例 | 行为 | 最佳使用场景 |
|---|---|---|---|
~ |
location ~ \.php$ |
匹配任何以 .php 结尾的 URI。 |
特定文件类型处理 (例如, 将 PHP 脚本传递给 PHP-FPM)。 |
5. 不区分大小写的正则表达式 (~*)
与 ~ 相同,但匹配忽略 URI 的大小写。
| 修饰符 | 示例 | 行为 | 最佳使用场景 |
|---|---|---|---|
~* |
location ~* \.(jpg|gif|png)$ |
匹配图像文件扩展名,无论大小写如何 (例如, .JPG 或 .png)。 |
处理大小写一致性可能存在问题的文件。 |
关键的 Location 处理顺序
理解 Nginx 处理 location 块的顺序对于避免意外行为至关重要。Nginx 不会 简单地从上到下读取配置文件。它使用严格的层次结构:
- 精确匹配 (
=): Nginx 首先检查所有精确匹配块。如果找到匹配项,处理立即停止,请求由该块处理。 - 最长前缀匹配覆盖 (
^~): Nginx 接着搜索所有使用^~定义的 location 块。如果找到了最长匹配,处理立即停止。 - 正则表达式 (
~和~*): 如果请求未被=或^~处理,Nginx 会按它们在配置文件中出现的顺序检查所有正则 location(~和~*)。第一个 匹配的块将被使用,并且处理停止。 - 最长标准前缀匹配(无修饰符): 如果未找到正则匹配,Nginx 最终使用最长匹配的标准前缀 location(即没有修饰符的那些)。
- 兜底匹配 (
location /): 如果没有其他块匹配,则使用根 location (/) 作为回退处理器。
提示: 如果您有一个比标准前缀匹配更长的
^~匹配,那么^~将始终获胜,并阻止检查正则块,即使某个正则块可以匹配该 URI。
实用配置场景
1. 优先处理静态资源以提高性能
为了确保 Nginx 直接快速地提供静态文件,防止较慢的正则检查和应用服务器进行不必要的处理,请使用 ^~ 修饰符。
server {
listen 80;
server_name myapp.com;
# 1. 主页的精确匹配(最高优先级)
location = / {
proxy_pass http://backend_app_server;
}
# 2. 静态资源的快速处理,绕过正则检查
location ^~ /static/ {
root /var/www/site;
expires 30d;
break;
}
# 3. 常见媒体文件的正则表达式
location ~* \.(gif|ico|css|js)$ {
root /var/www/site;
expires 7d;
}
# 4. 所有其他动态请求的回退
location / {
proxy_pass http://backend_app_server;
}
}
2. 路由和代理 API 流量
当 Nginx 用作反向代理时,location 块对于将流量导向正确的上游应用服务器至关重要。
location /api/v1/ {
# 确保 Nginx 尊重客户端连接设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 将所有以 /api/v1/ 开头的流量路由到后端服务
proxy_pass http://api_backend_service/v1/;
# 如果需要在将其传递给上游之前从 URI 中去除 /api/v1/,
# 您可以使用正则匹配和重写:
# location ~ ^/api/v1/(.*)$ {
# proxy_pass http://api_backend_service/$1;
# }
}
3. 保护敏感目录
Location 块可用于拒绝外部访问敏感的内部目录,例如配置文件或隐藏目录(如 .git)。
# 拒绝访问以点开头的文件(隐藏文件)
location ~ /\.(ht|svn|git) {
deny all;
return 404; # 返回 404 而不是 403,以避免泄露它们的存在
}
# 拒绝访问特定的配置目录
location /app/config/ {
deny all;
}
安全警告:使用
alias与root在 location 块内配置文件路径时,请注意
root和alias之间的区别。
root: 将完整的请求 URI 附加到定义的路径。 (例如,location /images/+root /data/导致路径为/data/images/filename.jpg)alias: 用定义的路径替换 URI 中匹配的部分。当 location 块使用正则表达式或需要在提供文件之前剥离部分路径时,这通常是必需的。 (例如,location /static/+alias /opt/app/files/导致路径为/opt/app/files/filename.jpg)
4. 处理末尾斜杠和重定向
通常需要强制执行一致的 URL 结构,例如确保目录始终以末尾斜杠 (/) 结束。
# 如果缺少,则强制为目录路径添加末尾斜杠
location ~* /[a-z0-9\-_]+$ {
# 如果 URI 匹配文件,Nginx 将尝试提供该文件。否则,将其视为目录。
# 检查请求的 URI 是否映射到磁盘上的目录:
if (-d $request_filename) {
return 301 $uri/;
}
}
结论
Nginx location 块是服务器配置的支柱,对每个传入请求提供了细粒度的控制。通过理解五个匹配修饰符(=、^~、~、~* 和前缀)以及严格的处理顺序,管理员可以创建高度优化、高效且可靠的路由配置。务必彻底测试更改,尤其是在混合使用前缀和正则表达式匹配时,以确保流量完全按预期流动。