Nginx 内置变量是 Nginx 配置中极具灵活性的核心特性,它们能动态获取请求、连接、服务器等维度的实时数据,让配置从"固定模板"升级为"智能响应"。本文将系统梳理常用内置变量的分类、含义,并结合实战案例说明其应用场景,帮助你真正用好 Nginx 变量。
一、Nginx 内置变量的核心特性
在深入变量前,先明确两个关键特性:
- 动态性 :变量值并非固定,而是在每次请求处理时实时生成(如
$remote_addr
会随客户端 IP 变化)。 - 作用域:变量仅在当前请求的处理周期内有效,不同请求的变量值相互独立。
- 命名规则 :所有内置变量均以
$
开头,如$uri
、$status
。
二、常用内置变量分类与含义
按"数据来源"可将内置变量分为 5 大类,涵盖请求、连接、服务器、响应等核心场景。
1. 请求相关变量(获取客户端请求信息)
这类变量用于获取客户端发送的请求细节,是最常用的变量类型。
变量名 | 含义 | 示例 |
---|---|---|
$remote_addr |
客户端真实 IP 地址(未经过代理时) | 192.168.230.1 (本地局域网 IP) |
$arg_xxx |
获取 URL 中 xxx 对应的参数值(xxx 为参数名) |
请求 http://xxx/?id=123 时,$arg_id=123 |
$args |
完整的 URL 请求参数(? 后面的所有内容) |
请求 http://xxx/?id=123&name=test 时,$args=id=123&name=test |
$request_method |
客户端请求方法(GET/POST/PUT/DELETE 等) | GET 、POST |
$request_uri |
完整的请求 URI(包含路径和参数,不包含域名) | 请求 http://xxx/api/user?uid=1 时,$request_uri=/api/user?uid=1 |
$uri / $document_uri |
请求的 URI 路径(不含参数,两者功能几乎一致) | 请求 http://xxx/api/user?uid=1 时,$uri=/api/user |
$http_xxx |
获取请求头中 xxx 字段的值(xxx 为请求头名,需将 - 改为小写) |
获取 User-Agent 时用 $http_user_agent ,获取 Referer 时用 $http_referer |
$cookie_xxx |
获取客户端 Cookie 中 xxx 对应的 value |
客户端 Cookie 为 token=abc123 时,$cookie_token=abc123 |
2. 连接相关变量(获取网络连接信息)
用于获取客户端与服务器之间的连接状态,常用于连接追踪和并发控制。
变量名 | 含义 | 示例 |
---|---|---|
$connection |
客户端与服务器的唯一连接 ID(每次新连接会生成新 ID) | 12345 (数字型 ID) |
$connection_requests |
当前连接上已处理的请求次数(长连接场景下会累计) | 同一连接发起第 3 次请求时,值为 3 |
$remote_port |
客户端用于连接的端口号 | 54321 (客户端随机端口) |
$server_port |
服务器监听的端口号(当前请求命中的端口) | 80 (HTTP)、443 (HTTPS) |
3. 服务器相关变量(获取服务器自身信息)
用于获取 Nginx 服务器的配置和系统信息,常用于多服务器部署场景。
变量名 | 含义 | 示例 |
---|---|---|
$server_addr |
服务器处理当前请求的 IP 地址(多网卡时对应绑定的 IP) | 192.168.230.130 (服务器内网 IP) |
$server_name |
当前请求命中的 server 块的 server_name 配置值 |
若 server_name www.example.com ,则值为 www.example.com |
$hostname |
服务器的系统主机名(与 hostname 命令输出一致) |
centos-nginx-server |
4. 响应相关变量(获取 Nginx 响应信息)
用于记录 Nginx 向客户端返回的响应数据,常用于日志统计和性能分析。
变量名 | 含义 | 示例 |
---|---|---|
$status |
响应的 HTTP 状态码 | 200 (成功)、404 (未找到)、502 (网关错误) |
$body_bytes_sent |
发送给客户端的响应体大小(单位:字节,不含响应头) | 返回 1KB 文本时,值为 1024 |
$bytes_sent |
发送给客户端的总字节数(含响应头 + 响应体) | 通常比 $body_bytes_sent 大 100-200 字节(响应头占比) |
$request_time |
请求的总处理耗时(单位:秒,精确到毫秒) | 0.005 (表示 5 毫秒) |
5. 时间相关变量(获取时间信息)
用于记录请求处理的时间,常用于日志时间戳和时间范围控制。
变量名 | 含义 | 示例 |
---|---|---|
$msec |
请求处理完成时的 Unix 时间戳(含毫秒,从 1970-01-01 开始) | 1724325600.123 (对应 2024-08-22 11:20:00.123) |
$time_local |
服务器本地时间(格式化字符串,含时区) | 22/Aug/2024:11:20:00 +0800 (+0800 表示北京时间) |
$time_iso8601 |
ISO 8601 标准时间(UTC 时间,无时区偏移) | 2024-08-22T03:20:00+00:00 |
三、内置变量实战案例
了解变量含义后,关键是知道"在什么场景用什么变量"。以下 5 个实战案例覆盖日志、鉴权、跳转、限流等高频场景。
案例 1:自定义访问日志(记录关键请求信息)
默认的 Nginx 访问日志仅包含基础信息,通过变量可自定义日志格式,记录如"客户端 IP、请求方法、参数、耗时"等关键数据,方便后续分析。
配置步骤:
-
在
nginx.conf
的http
块中定义日志格式:nginxhttp { # 1. 定义自定义日志格式(命名为 "detail_log") log_format detail_log '$remote_addr [$time_local] "$request_method $request_uri" ' 'status:$status args:"$args"耗时:$request_time ' 'user_agent:"$http_user_agent"'; # 2. 启用自定义日志(指定日志路径和格式) access_log /usr/local/nginx/logs/detail_access.log detail_log; # 其他配置... }
-
重载 Nginx 配置:
bash/usr/local/nginx/sbin/nginx -t # 检查语法 /usr/local/nginx/sbin/nginx -s reload # 重载生效
日志效果:
访问 http://192.168.230.130/?id=123
后,日志文件会生成如下记录:
ini
192.168.230.1 [22/Aug/2024:11:30:00 +0800] "GET /?id=123" status:200 args:"id=123"耗时:0.002 user_agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/127.0.0.1"
案例 2:URL 参数鉴权(限制特定参数访问)
场景:仅允许 token
参数为 abc123
的请求访问 /admin
路径,否则返回 403 禁止访问。
配置步骤:
在 server
块中添加 location
规则:
nginx
server {
listen 80;
server_name localhost;
# 匹配 /admin 路径
location /admin {
# 1. 检查 $arg_token(URL 中 token 参数)是否等于 abc123
if ($arg_token != "abc123") {
return 403 "Forbidden: Invalid token\n"; # 不匹配则返回 403
}
# 2. 匹配通过时的处理(如返回 admin 页面)
default_type text/html;
return 200 "<h1>Admin Page (Token Valid)</h1>";
}
}
测试效果:
- 合法请求:
http://192.168.230.130/admin?token=abc123
→ 返回 200 和 Admin 页面。 - 非法请求:
http://192.168.230.130/admin?token=wrong
→ 返回 403 和 "Forbidden"。
案例 3:根据客户端 IP 跳转(本地 IP 免验证)
场景:局域网 IP(192.168.230.xxx
)访问 /login
时直接跳转至首页,其他 IP 正常显示登录页。
配置步骤:
利用 $remote_addr
判断客户端 IP,结合 rewrite
实现跳转:
nginx
server {
listen 80;
server_name localhost;
location /login {
# 1. 匹配局域网 IP(以 192.168.230. 开头)
if ($remote_addr ~* ^192\.168\.230\.) {
rewrite ^/login$ / permanent; # 301 永久跳转到首页
}
# 2. 其他 IP 显示登录页
default_type text/html;
return 200 "<h1>Login Page (Non-Local IP)</h1>";
}
# 首页配置
location / {
default_type text/html;
return 200 "<h1>Home Page (Local IP Bypassed Login)</h1>";
}
}
测试效果:
- 本地 IP(如
192.168.230.1
)访问/login
→ 自动跳转到/
(首页)。 - 外部 IP(如
10.0.0.1
)访问/login
→ 显示登录页。
案例 4:根据请求头切换后端服务(前后端分离场景)
场景:请求头 X-Request-Type
为 api
时,转发请求到后端 API 服务(127.0.0.1:8080
);否则返回静态页面。
配置步骤:
利用 $http_x_request_type
获取自定义请求头,结合 proxy_pass
实现反向代理:
nginx
server {
listen 80;
server_name localhost;
location / {
# 1. 判断请求头 X-Request-Type 是否为 api
if ($http_x_request_type = "api") {
proxy_pass http://127.0.0.1:8080; # 转发到 API 服务
proxy_set_header Host $host; # 传递 Host 头给后端
break; # 跳出 if,避免后续执行
}
# 2. 其他请求返回静态首页
root /usr/local/nginx/html;
index index.html;
}
}
测试效果:
-
发送 API 请求(带请求头):
bashcurl -H "X-Request-Type: api" http://192.168.230.130/api/user
→ 请求被转发到
127.0.0.1:8080/api/user
。 -
普通访问:
http://192.168.230.130
→ 返回/usr/local/nginx/html/index.html
。
案例 5:基于 Cookie 实现灰度发布(部分用户尝鲜新功能)
场景:Cookie 中 version=beta
的用户访问 /feature
时,返回新功能页面;其他用户返回旧页面。
配置步骤:
利用 $cookie_version
获取 Cookie 值,实现灰度分流:
nginx
server {
listen 80;
server_name localhost;
location /feature {
default_type text/html;
# 1. 检查 Cookie 中 version 是否为 beta
if ($cookie_version = "beta") {
return 200 "<h1>New Feature (Beta Version)</h1>"; # 新功能
}
# 2. 其他用户显示旧功能
return 200 "<h1>Old Feature (Stable Version)</h1>";
}
}
测试效果:
-
灰度用户(带 Cookie):
bashcurl -b "version=beta" http://192.168.230.130/feature
→ 返回 "New Feature (Beta Version)"。
-
普通用户(无 Cookie):
bashcurl http://192.168.230.130/feature
→ 返回 "Old Feature (Stable Version)"。
四、使用内置变量的注意事项
- 避免过度使用
if
指令 :Nginx 的if
指令在某些场景下可能触发意外行为(如与try_files
冲突),复杂逻辑优先用map
指令或 Lua 脚本。 - 代理场景下的 IP 问题 :若 Nginx 位于代理服务器后(如 CDN、负载均衡器),
$remote_addr
会变为代理 IP,需通过$http_x_forwarded_for
获取客户端真实 IP(需代理服务器传递该请求头)。 - 变量大小写敏感 :
$arg_id
和$arg_ID
是两个不同的变量(前者对应?id=1
,后者对应?ID=1
),配置时需注意参数名大小写。 - 性能影响 :内置变量本身性能开销极低,但频繁使用复杂正则匹配(如
if ($remote_addr ~* ...)
)可能增加 CPU 消耗,高并发场景需优化正则。
五、总结
Nginx 内置变量是连接"静态配置"与"动态请求"的桥梁,掌握它们能让你摆脱固定配置的束缚,实现更灵活的请求处理逻辑。本文梳理的 5 大类变量和实战案例,覆盖了日志、鉴权、跳转、代理、灰度等高频场景,建议结合实际需求动手测试------只有在实践中反复使用,才能真正理解变量的威力。
如果需要更复杂的场景(如结合 map
指令批量处理变量、Lua 脚本扩展变量功能),可以进一步深入学习 Nginx 高级配置技巧。