$request_completion不能直接判断静态资源是否完整下载,仅反映Nginx响应发送流程结束;需结合$bytes_sent与$content_length比对、异常状态分析及客户端验证才能可靠监控。

$request_completion 本身不能直接判断静态资源是否被完整下载,它只反映 Nginx 请求生命周期的最终状态,而非传输过程的完整性。对静态资源(如 JS、CSS、图片、字体等)而言,“下载完成”意味着响应体已全部发送给客户端且连接正常关闭;而 $request_completion 的 OK 状态仅表示 Nginx 成功发起并结束响应发送流程,并不保证客户端实际接收完毕——例如用户中途关闭标签页、网络中断、浏览器崩溃等情况,Nginx 可能仍记录为 OK。
要可靠监控静态资源是否被完整下载,需结合多个指标与机制:
关注 $request_completion 的异常信号
虽然它不直接说明“下载完成”,但它的非 OK 值是关键预警线索:
-
TIMEOUT:常见于客户端提前断开(如页面跳转、刷新、切后台),尤其在大文件(如视频、PDF)或弱网环境下,提示资源极可能未下载完; -
ERROR:Nginx 自身出错(如磁盘满导致 sendfile 失败、权限拒绝读取文件),此时资源根本未发出,必然未完成; - 注意:
OK不等于“客户端收到了全部字节”,仅表示 Nginx 认为自己发完了。
必须搭配 $bytes_sent 和 $content_length 对比
这是验证静态资源传输完整性的最直接方式:
-
$bytes_sent:Nginx 实际发送的响应体字节数(不含响应头); -
$content_length:响应头中声明的内容长度(由add_header Content-Length或 Nginx 自动计算); - 在 access log 中记录二者,例如:
log_format static_complete '$time_local $uri $status $request_completion ' '$bytes_sent $content_length $upstream_status'; - 分析时筛选静态资源路径(如
\.js$|\.css$|\.png$|\.woff2?$),检查:$bytes_sent → 明确未发完(可能是连接中断或限速截断);-
$bytes_sent == $content_length且$request_completion == "OK"→ 高概率完整发送; -
$content_length为空(-)且$bytes_sent > 0→ 使用了 chunked 编码,此时需依赖客户端侧确认(见下文)。
启用并分析 Nginx 的 sendfile 与 tcp_nopush 行为
静态资源通常走 sendfile 零拷贝路径:
- 若
sendfile on;且文件未被修改,Nginx 会委托内核发送,$bytes_sent准确反映内核实际写出的字节数; - 但若发生
sendfile失败(如文件被删除、权限变化),Nginx 会回退到用户态读写,此时更易出现不一致; - 可在 error log 中开启
debug_http级别(谨慎生产使用),搜索sendfile: -1或writev: Connection reset by peer等线索。
客户端侧补充验证(必要时)
服务端日志无法得知浏览器是否解析/加载成功,对关键静态资源(如核心 JS),建议:
- 在 HTML 中内联轻量 JS,监听
onload或performance.getEntriesByType("resource"),上报transferSize与encodedBodySize; - 使用
navigator.onLine+fetch().then(r => r.arrayBuffer())主动探测资源可读性; - 结合 Instana 或 OpenTelemetry 前端 SDK,捕获资源加载事件(含
duration、decodedBodySize、nextHopProtocol)。
不复杂但容易忽略。










