nginx变量默认延迟加载且单请求内缓存,仅$remote_addr等解析后变量及无NOCACHEABLE标志者缓存;$request_time、$time_local等带NOCACHEABLE标志的变量每次读取重算。

nginx 中的 $variable 并非在配置解析阶段就全部求值,而是按需计算、延迟加载(Lazy Loading),且多数变量具备一次求值、多次复用的缓存行为。这种机制既保障了性能,又支撑了条件判断、日志记录、重写等动态场景的灵活性。
哪些变量会延迟加载?
所有以 $ 开头的内置变量(如 $remote_addr、$request_uri、$status)和模块定义的变量(如 $upstream_http_x_trace_id)默认都采用延迟加载策略。它们不会在读取配置时立即执行,而是在实际被引用的上下文(例如 log_format、if、set、proxy_set_header)中首次访问时才触发计算逻辑。
例外情况极少:极少数变量(如 $nginx_version 或 $pid)在进程启动时已确定,但即便如此,其值仍通过延迟加载接口返回,只是内部实现直接返回常量。
变量值如何被缓存?
nginx 对绝大多数请求级变量采用“单请求生命周期内缓存”策略——即一个变量在当前请求处理过程中,一旦被计算过,后续再访问同一变量将直接返回缓存结果,不再重复调用其 get_handler 回调函数。
-
$request_time在请求结束前始终为未完成值,每次读取都重新计算(不缓存) -
$uri、$args、$host等解析类变量,在 URI 解析完成后即缓存,后续读取不触发重解析 -
$sent_http_*类响应头变量,仅在响应头已发送后才可获取,且缓存的是最终输出值 - 自定义模块通过
ngx_http_get_variable获取变量时,同样享受该缓存机制,无需自行维护
影响缓存行为的关键因素
变量是否真正被缓存,取决于其注册时指定的 flags 字段,尤其是 NGX_HTTP_VAR_NOCACHEABLE 和 NGX_HTTP_VAR_NOHASH 标志位:
- 带
NOCACHEABLE标志的变量(如$time_local、$msec)每次访问都强制重新计算,不缓存 - 未设该标志的变量,默认启用缓存,且 nginx 会自动管理其生命周期(与请求周期对齐)
- 变量索引在
variables数组中静态建立,但值存储在r->variables数组中,按需填充
开发者注意事项
在编写自研模块并声明新变量时,若需控制缓存行为,应在 ngx_http_variable_t 结构体中正确设置 flags:
- 希望变量每次读取都刷新(如实时计数器、时间戳),务必添加
NGX_HTTP_VAR_NOCACHEABLE - 若变量依赖上游响应(如
$upstream_status),应确保其get_handler能安全处理“尚未产生响应”的状态 - 避免在
get_handler中执行耗时操作,因该函数可能在高并发路径上被频繁调用











