$request_completion 仅标识请求最终状态(OK/ERROR/TIMEOUT),无法直接定位业务阶段,需结合$upstream_status、$upstream_connect_time等变量及debug日志或Lua阶段标记协同分析。

$request_completion 是 Nginx 内置变量,用于标识当前请求的完成状态,但它本身不直接记录中断发生在哪个业务阶段。它仅返回三个固定值:OK(正常完成)、ERROR(服务端错误)、TIMEOUT(客户端超时或连接中断)。因此,单靠该变量无法定位“具体业务阶段”(如鉴权、路由转发、上游响应解析等),但可作为关键线索,配合其他手段实现精准归因。
理解 $request_completion 的实际含义
该变量反映的是 Nginx 处理请求生命周期的最终结果,而非中间过程:
-
OK:Nginx 已成功将响应(无论内容是否正确)发送给客户端,且连接正常关闭; -
ERROR:Nginx 自身在处理中遇到不可恢复错误(如 upstream 无可用服务器、rewrite 循环、内存分配失败),不是后端应用返回的 5xx; -
TIMEOUT:客户端主动断开(如浏览器取消请求、移动端切网)、客户端读取响应超时(client_timeout)、或 Nginx 等待 upstream 响应超时(proxy_read_timeout等)。
结合日志与上下文定位业务阶段
要识别中断发生的具体阶段,需将 $request_completion 与其他变量和日志字段交叉分析:
- 搭配
$upstream_status:若为TIMEOUT且$upstream_status为空或-,说明中断发生在 upstream 连接建立前(如 DNS 解析失败、TCP 握手失败、负载均衡选不到节点);若$upstream_status有值(如504),则中断大概率在 upstream 响应阶段; - 搭配
$upstream_connect_time与$upstream_header_time:若前者为-或极小(如0.000),而后者为空,说明卡在建连;若前者正常但后者为空或极大,说明卡在等待 upstream 首行响应; - 启用
error_log的debug级别(谨慎使用):可捕获 Nginx 内部状态流转,例如http proxy phase: 6(表示已进入 upstream 转发阶段),结合时间戳可反推中断点; - 在关键位置插入自定义日志:例如在
location /api/块开头记录"stage=auth",在proxy_pass前记录"stage=route",再配合$request_completion和$time_local,即可比对哪段日志缺失。
利用 OpenResty 或 Lua 增强阶段感知能力
纯 Nginx 配置难以动态标记业务阶段,OpenResty 提供了精细控制入口:
- 在
access_by_lua_block中执行鉴权逻辑,并设置ngx.ctx.stage = "auth"; - 在
balancer_by_lua_block中选择上游前记录ngx.ctx.stage = "upstream_select"; - 在
log_by_lua_block中统一输出:ngx.log(ngx.INFO, string.format("req_id=%s stage=%s completion=%s", ngx.var.request_id, ngx.ctx.stage or "unknown", ngx.var.request_completion)); - 这样每条日志都携带明确的阶段标签,配合
$request_completion即可直接锁定失败环节。
排查典型场景示例
例如日志中高频出现 completion=TIMEOUT,且 upstream_connect_time=-、upstream_header_time=-:
- 先检查 upstream server 是否配置了
max_fails和fail_timeout,是否因健康检查失败被摘除; - 用
tcpdump抓包确认客户端到 Nginx、Nginx 到 upstream 的 TCP 连接是否能建立; - 检查
proxy_next_upstream timeout是否开启——若未开启,单个 upstream 超时即直接返回 504,$request_completion为ERROR,而非TIMEOUT。
不复杂但容易忽略。

















