应直接使用 $request_time 统计 nginx 静态资源真实耗时,配合专用日志格式、按后缀分离 location 块、启用 open_file_cache 状态头,并借助 prometheus 或 loki 等外部工具聚合计算平均延迟。

直接看 $request_time,它就是 Nginx 处理静态资源的真实耗时——从收完请求头开始,到发完响应体结束,覆盖文件打开、读取、发送全过程。静态资源不走 upstream,所以 $upstream_response_time 没意义,必须用这个变量。
确保日志格式里明确记录它:
log_format static_log '$remote_addr - [$time_local] "$request" $status $body_bytes_sent $request_time $msec';
注意:`$time_local` 只精确到秒,不能用来算延迟;`$msec` 提供毫秒级时间戳,方便对齐和排查时序问题。
按路径分离静态请求,避免混入动态流量干扰
在匹配静态后缀的 location 块中启用专用日志:
- location ~* \.(js|css|png|jpg|gif|ico|svg|woff2?)$ {
- access_log /var/log/nginx/static_access.log static_log;
- expires 1h;
- add_header X-Static-Hit $sent_http_content_length;
- add_header X-File-Cache $upstream_cache_status;
- }
这样能隔离出纯静态请求流,后续统计才干净。`X-File-Cache` 能帮你确认是否命中 `open_file_cache`(注意:直连 root/alias 时该变量仍有效,值为 HIT/MISS/BYPASS)。
用外部工具聚合,Nginx 自身不计算平均值
原始日志要交给支持聚合的系统处理:
- Prometheus + nginx-prometheus-exporter:开启 `--enable-static-stats` 后,指标 `nginx_static_request_seconds_sum / nginx_static_request_seconds_count` 就是平均响应时间(单位秒)
- Loki + Grafana:用 LogQL 提取 `$request_time` 字段,再用 `avg_over_time({job="nginx"} |~ `GET.*\.(js|css)` | regexp `"(\d+\.\d+)"` | unwrap __error__ [5m])` 计算 5 分钟内 JS/CSS 的平均延迟
- 临时排查可用 awk:`awk '{if($NF > 0 && $NF
别被平均值带偏,P95 更关键
平均响应时间容易被少量慢请求拉高或压低,看不出长尾问题。建议同步看 P95(95% 请求低于该值),比如在 Grafana 中用:
histogram_quantile(0.95, sum(rate(nginx_static_request_seconds_bucket[5m])) by (le))
如果 P95 明显高于平均值,说明存在抖动或缓存未命中集中爆发,需结合 `X-File-Cache` 标签进一步下钻。











