$host 和 $body_bytes_sent 是 Nginx 中区分站点并统计静态资源流量的核心字段,需在 log_format 中定义、各 server 块独立启用日志文件,并通过 tail/awk 或 ELK 实时聚合分析,注意 304/204 等响应体为 0、CDN 回源需过滤、gzip 后字节数已自动计入。

在 Nginx 中,$body_bytes_sent 变量记录了响应体实际发送给客户端的字节数(不包括响应头),是统计静态资源流量消耗最直接、最准确的指标。要实时统计各站点的静态流量,关键在于:在 log_format 中定义带站点标识(如 $host 或 $server_name)和 $body_bytes_sent 的日志格式,并确保日志按需切分与采集分析。
配置带站点与流量字段的 log_format
在 http 块中定义自定义日志格式,包含站点域名和响应字节数:
log_format flow_log '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
说明:
• $host 使用请求头中的 Host 字段,能区分同一 IP 下多个虚拟主机;若需严格匹配 server 块配置,可用 $server_name(但注意它不随请求动态变化);
• $body_bytes_sent 是真实发出的响应体字节,对 200/304/206 等响应均有效,比 $bytes_sent(含响应头)更聚焦静态内容本身;
• 日志字段顺序建议把 $host 放首位,便于后续用 awk/grep 或日志系统按域名聚合。
为各 server 块启用该日志格式
在每个站点的 server 块中,指定 access_log 使用该格式,并推荐按天切分:
server {
listen 80;
server_name example.com;
root /var/www/example;
<pre class='brush:php;toolbar:false;'>access_log /var/log/nginx/example.com-access.log flow_log;
# 可选:按天切分(配合 logrotate 或定时脚本)}
注意:
• 不同站点必须使用不同日志文件路径,否则无法分离统计;
• 若所有站点共用一个 access_log 文件,需靠 $host 字段在分析阶段过滤,但会增加解析开销;
• 静态资源(如 .js/.css/.png)通常由 Nginx 直接返回,其响应天然计入 $body_bytes_sent,无需额外 location 匹配。
实时采集与轻量统计方法
无需引入复杂监控系统,即可快速获得各站点每分钟/每小时流量:
- 用
tail -f+awk实时汇总(示例:过去 10 秒内各域名总流量):tail -F /var/log/nginx/*.log | awk '{sum[$1] += $7} END {for (h in sum) print h, sum[h]}' - 配合
chrony或systemd-timers每 5 分钟执行一次聚合脚本,写入临时 CSV:awk '$7 > 0 {t[$1] += $7} END {for (i in t) print strftime("%Y-%m-%d %H:%M"), i, t[i]}' /var/log/nginx/example.com-access.log.1 - 若已接入 ELK 或 Grafana Loki,将
$host和$body_bytes_sent映射为结构化字段,可直接按域名做 rate()、sum_over_time() 聚合。
注意事项与常见问题
不是所有响应都计入 $body_bytes_sent:304 Not Modified、204 No Content、部分错误页(如 404 默认页)可能为 0 字节,属正常现象;
避免重复计费或误统计:CDN 回源日志也含此变量,若统计的是“源站发出流量”,需确保只采集来自 CDN IP 的日志,或在日志中加入 $http_x_forwarded_for 辅助判断;
gzip 影响已自动处理:Nginx 在计算 $body_bytes_sent 时,使用的是**压缩后实际写出的字节数**,即用户真实接收量,无需额外解压还原;
日志权限与磁盘水位:高流量站点单日日志可达 GB 级,务必配置 logrotate 并监控 /var/log/nginx/ 分区使用率。

















