$upstream_status为"-"表示请求未发往upstream,原因包括try_files本地响应、proxy_cache命中、return/error_page拦截、rewrite break或internal跳转等,需结合$request_uri、$status、$upstream_addr等变量定位。

当 Nginx 日志中 $upstream_status 显示为 "-",说明该请求根本没发往 upstream——它被本地拦截、重定向、缓存命中,或压根没走 proxy_pass。这不是配置错误,而是行为事实,关键在于识别原因并针对性处理。
哪些情况会导致 $upstream_status 为 "-"
该变量只在真正发起 upstream 请求并收到响应后才被赋值。以下情形均不会触发 upstream 通信:
- 请求被
try_files直接由本地文件响应(如静态资源命中) - 命中
proxy_cache缓存且未过期,直接返回缓存内容 - 被
return或error_page拦截(如return 404、error_page 404 =200 /fallback.html) - 匹配到
location ~ \.php$但实际用的是fastcgi_pass,此时应查$upstream_status不适用,需改用$upstream_addr和$upstream_response_time配合判断 - 使用了
rewrite ... break或内部跳转(internal),未进入 upstream 流程
如何快速定位为什么是 "-"
单靠 $upstream_status 无法溯源,必须搭配其他变量交叉验证:
- 在
log_format中同时记录$request_uri、$status、$upstream_addr和$upstream_response_time - 若
$upstream_addr也为 "-",基本确认未出代理;若$upstream_addr有值但$upstream_status是 "-",可能是 upstream 响应头异常(如缺失状态行)导致解析失败 - 检查
$status:如果是 301/302/304/200 且无 upstream 耗时,大概率是重定向或缓存生效 - 开启
error_log的info级别(error_log logs/error.log info;),可看到每条请求是否进入upstream_init阶段
避免误判的实用技巧
不要把 "-" 当作“异常”,它本身是合法状态。重点应放在业务逻辑是否符合预期:
- 对 API 接口类 location,强制要求必须走 upstream:可在配置中加
proxy_set_header X-Upstream-Required "1";,并在日志里加$http_x_upstream_required字段,便于筛选漏掉代理的请求 - 若想统一记录所有请求的后端耗时,可用
$request_time减去$upstream_response_time估算 Nginx 自身处理开销(仅当$upstream_response_time非 "-" 时有效) - 监控时过滤掉
$upstream_status = "-"的日志行,再统计 5xx 比例,否则会拉低分母导致告警失灵 - 调试阶段可临时加
add_header X-Upstream-Status $upstream_status;到响应头,用 curl 直观查看
特别注意 Windows 下的兼容细节
Windows 版 Nginx 对 $upstream_status 的支持从 1.7.10 起稳定,但旧版本(如 1.6.x)可能始终输出 "-"。确认版本:nginx -v。若无法升级,可用 $upstream_addr 是否为空作为间接判断依据——空则大概率未转发。











