$request_completion 是 Nginx 仅在日志阶段可用的内置变量,请求完整结束时为"ok",中断时为空字符串,专用于下载完成状态记录与分析。

$request_completion 是 Nginx 内置变量,仅在请求**结束时**(即响应已完全发送给客户端后)被赋值为 "ok";若请求被中断(如客户端断开、超时、主动取消),则值为 ""(空字符串)。它不参与请求处理流程,不能用于条件跳转或 rewrite,但非常适合用于**日志记录和事后分析**,尤其适用于监控大文件下载是否完整送达。
确认 $request_completion 的行为边界
该变量只在 log phase(日志写入阶段)可用,因此只能用在 log_format 或 access_log 指令中。在 if、set、rewrite 等指令中引用会始终为空,属于常见误用点。
- ✅ 正确:写进自定义日志格式,配合 access_log 使用
- ❌ 错误:在 location 块里写
if ($request_completion = "ok") { ... } - ⚠️ 注意:即使启用
sendfile on或tcp_nopush on,只要内核完成 TCP 发送并连接正常关闭,Nginx 仍会判定为 "ok"
配置带 $request_completion 的下载日志
为精准追踪大文件下载结果,建议单独为下载路径(如 /dl/)配置专用日志格式:
log_format download '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_completion';
然后在对应 location 中启用:
location /dl/ {
alias /var/www/downloads/;
access_log /var/log/nginx/download.log download;
# 可选:限制并发、启用 range 支持、添加 X-Accel-Redirect 等
}
日志样例:
- 成功完成:
192.168.1.100 - - [10/Jan/2025:14:22:33 +0800] "GET /dl/big.zip HTTP/1.1" 200 1073741824 "-" "curl/8.6.0" ok - 中途断开:
192.168.1.100 - - [10/Jan/2025:14:22:35 +0800] "GET /dl/big.zip HTTP/1.1" 200 283920512 "-" "curl/8.6.0"(末尾无内容,即空字符串)
结合日志分析识别失败下载
利用标准 Linux 工具即可快速统计:
- 统计全部下载中完成率:
awk '{print $12}' /var/log/nginx/download.log | sort | uniq -c - 查出所有未完成的请求(空字段):
awk '$12 == "" {print $0}' /var/log/nginx/download.log - 按客户端 IP 汇总失败次数:
awk '$12 == "" {print $1}' /var/log/nginx/download.log | sort | uniq -c | sort -nr
注意:$body_bytes_sent 是已发送字节数,可与文件实际大小比对(需提前知道目标文件 size),辅助判断是“完全失败”还是“部分传输”。例如某 1GB 文件,日志中 $body_bytes_sent = 123456789 且 $request_completion 为空,说明传输约 118MB 后中断。
增强可观测性的实用建议
单靠 $request_completion 不足以定位根因,建议组合以下手段:
- 开启
error_log /var/log/nginx/error.log notice;,关注client closed connection、Broken pipe类错误 - 对大文件接口启用
add_header X-Download-Status $request_completion;(仅作调试参考,不推荐生产返回该头) - 配合 Nginx Plus 或开源方案(如 nginx-module-vts)做实时连接状态监控
- 在应用层(如后端生成下载链接时)注入唯一 trace_id,并记录到日志中,便于跨系统关联分析











