注册

Nginx 内置变量详解:从原理到实战案例

Nginx 内置变量是 Nginx 配置中极具灵活性的核心特性,它们能动态获取请求、连接、服务器等维度的实时数据,让配置从“固定模板”升级为“智能响应”。本文将系统梳理常用内置变量的分类、含义,并结合实战案例说明其应用场景,帮助你真正用好 Nginx 变量。


一、Nginx 内置变量的核心特性


在深入变量前,先明确两个关键特性:



  1. 动态性:变量值并非固定,而是在每次请求处理时实时生成(如 $remote_addr 会随客户端 IP 变化)。
  2. 作用域:变量仅在当前请求的处理周期内有效,不同请求的变量值相互独立。
  3. 命名规则:所有内置变量均以 $ 开头,如 $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 等)GETPOST
$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 http://www.example.com,则值为 http://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_iso8601ISO 8601 标准时间(UTC 时间,无时区偏移)2024-08-22T03:20:00+00:00

三、内置变量实战案例


了解变量含义后,关键是知道“在什么场景用什么变量”。以下 5 个实战案例覆盖日志、鉴权、跳转、限流等高频场景。


案例 1:自定义访问日志(记录关键请求信息)


默认的 Nginx 访问日志仅包含基础信息,通过变量可自定义日志格式,记录如“客户端 IP、请求方法、参数、耗时”等关键数据,方便后续分析。


配置步骤:



  1. nginx.confhttp 块中定义日志格式:
    http {
    # 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;

    # 其他配置...
    }


  2. 重载 Nginx 配置:
    /usr/local/nginx/sbin/nginx -t  # 检查语法
    /usr/local/nginx/sbin/nginx -s reload # 重载生效



日志效果:


访问 http://192.168.230.130/?id=123 后,日志文件会生成如下记录:


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 规则:


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>";
}
}

测试效果:



案例 3:根据客户端 IP 跳转(本地 IP 免验证)


场景:局域网 IP(192.168.230.xxx)访问 /login 时直接跳转至首页,其他 IP 正常显示登录页。


配置步骤:


利用 $remote_addr 判断客户端 IP,结合 rewrite 实现跳转:


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-Typeapi 时,转发请求到后端 API 服务(127.0.0.1:8080);否则返回静态页面。


配置步骤:


利用 $http_x_request_type 获取自定义请求头,结合 proxy_pass 实现反向代理:


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;
}
}

测试效果:



案例 5:基于 Cookie 实现灰度发布(部分用户尝鲜新功能)


场景:Cookie 中 version=beta 的用户访问 /feature 时,返回新功能页面;其他用户返回旧页面。


配置步骤:


利用 $cookie_version 获取 Cookie 值,实现灰度分流:


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>";
}
}

测试效果:



四、使用内置变量的注意事项



  1. 避免过度使用 if 指令:Nginx 的 if 指令在某些场景下可能触发意外行为(如与 try_files 冲突),复杂逻辑优先用 map 指令或 Lua 脚本。
  2. 代理场景下的 IP 问题:若 Nginx 位于代理服务器后(如 CDN、负载均衡器),$remote_addr 会变为代理 IP,需通过 $http_x_forwarded_for 获取客户端真实 IP(需代理服务器传递该请求头)。
  3. 变量大小写敏感$arg_id$arg_ID 是两个不同的变量(前者对应 ?id=1,后者对应 ?ID=1),配置时需注意参数名大小写。
  4. 性能影响:内置变量本身性能开销极低,但频繁使用复杂正则匹配(如 if ($remote_addr ~* ...))可能增加 CPU 消耗,高并发场景需优化正则。

五、总结


Nginx 内置变量是连接“静态配置”与“动态请求”的桥梁,掌握它们能让你摆脱固定配置的束缚,实现更灵活的请求处理逻辑。本文梳理的 5 大类变量和实战案例,覆盖了日志、鉴权、跳转、代理、灰度等高频场景,建议结合实际需求动手测试——只有在实践中反复使用,才能真正理解变量的威力。


如果需要更复杂的场景(如结合 map 指令批量处理变量、Lua 脚本扩展变量功能),可以进一步深入学习 Nginx 高级配置技巧。


作者:灰色头像
来源:juejin.cn/post/7543193023086575625

0 个评论

要回复文章请先登录注册