$request_completion == "OK" 表示 Nginx 已完成响应发送并正常关闭连接,客户端极大概率收到全部响应;非 OK 则必然未收全,但 OK 不代表客户端应用层处理成功,需结合 $bytes_sent、$upstream_response_length 等字段交叉验证。

$request_completion 本身不能直接告诉你“客户端是否完整接收了响应”,但它能明确反映 Nginx 是否成功把响应发完并正常关闭连接——这是判断客户端是否有机会完整接收的最关键服务端依据。
要监控代理请求是否被客户端完整接收,核心逻辑是:
✅ $request_completion == "OK" → Nginx 已完成发送、连接干净关闭 → 客户端极大概率已收到全部响应体(前提是网络链路中间无丢包或代理截断);
❌ $request_completion == "TIMEOUT" 或 "ERROR" → Nginx 未完成发送 → 客户端必然未收全(或根本没收到)。
但注意:OK 不等于“客户端应用层确认处理成功”,它只代表 TCP 层传输完成。真正落地还需结合其他信号交叉验证。
看 $request_completion 的同时必须关注 upstream 和客户端行为
$request_completion是结果,不是原因。单看它只能做二分判断,无法归因。它和
$upstream_status、$upstream_response_length、$bytes_sent、$status组合才有意义:若
$request_completion == "OK"但$status == 200且$bytes_sent明显小于预期(比如后端应返回 1MB JSON,但$bytes_sent只有 12KB),说明响应可能被截断(如proxy_buffer_size不足、proxy_max_temp_file_size触发写临时文件失败等);若
$request_completion == "TIMEOUT"且$upstream_status为空或-,大概率是客户端提前断连(如页面跳转、刷新、APP切后台),此时即使 upstream 已返回完整响应,Nginx 也未能发完;若
$request_completion == "OK"但客户端日志/前端埋点显示“响应解析失败”或“空响应”,需检查 Nginx 是否做了不兼容的 header 修改(如误删Content-Length)、或启用了chunked_transfer_encoding但客户端不支持。
在日志中构建可验证的接收完整性字段
建议在 log_format 中固定加入以下变量,便于后续分析:
log_format complete_check '$time_local\t' '$request_completion\t' '$status\t' '$upstream_status\t' '$bytes_sent\t' '$upstream_response_length\t' '$request_length\t' '$http_user_agent';
关键看三组对比:
-
$bytes_sentvs$upstream_response_length:若前者显著偏小,说明 Nginx 未发出全部内容; -
$request_completionvs$status:OK+5xx表示后端出错但 Nginx 仍发完了错误页;OK+200才是理想通路; -
$bytes_sent的分布统计:对同一接口,若某段时间内$bytes_sent集中在某个偏低值(如总是卡在 65536 字节),提示缓冲区或超时配置异常。
补充手段提升判断置信度
仅靠 access log 有盲区,建议叠加:
- 启用
error_log ... debug;(生产慎用)观察http proxy phase流转,确认是否走到send response阶段; - 对关键接口,在
location块中用add_header X-Response-Sent "$bytes_sent";将实际发出字节数透传给客户端,前端可比对; - 结合客户端主动上报:例如前端 fetch 请求后记录
response.headers.get('content-length')与response.bodyUsed状态,和服务端$bytes_sent对齐校验。
不复杂但容易忽略。










