log_format本身不能实时监控带宽水位,但通过记录$backend_id和$body_bytes_sent字段,结合外部工具可实现秒级带宽聚合与可视化。

直接用 log_format 本身不能“实时监控”带宽水位,但它能输出关键字段,为秒级统计提供结构化基础。核心思路是:在日志中记录每个请求的响应体大小($body_bytes_sent)和所属节点标识($backend_id),再配合外部工具按时间窗口聚合计算带宽。
一、日志格式必须包含两个关键变量
带宽水位 = 单位时间(如每秒)内各节点发出的字节数总和。因此日志需同时携带:
- $body_bytes_sent:本次响应实际发送的字节数(不含响应头),是计算出向带宽的直接依据;
-
$backend_id:通过
map $upstream_addr $backend_id映射得到的节点别名(如node-a),用于区分集群成员。
示例配置(放在 http 块):
map $upstream_addr $backend_id {
default "unknown";
"10.0.1.10:8080" "node-a";
"10.0.1.11:8080" "node-b";
"10.0.1.12:8080" "node-c";
}
log_format bandwidth_log '$time_iso8601|$backend_id|$body_bytes_sent';
access_log /var/log/nginx/bandwidth.log bandwidth_log;
二、用轻量工具实现秒级带宽聚合
不依赖重型平台,可用以下方式快速落地:
- 用
tail -f实时读取日志,配合awk每秒统计各节点总字节数(即 Mbps 级带宽); - 例如,下面命令每秒打印一次各节点上一秒的带宽(单位:KB/s):
tail -f /var/log/nginx/bandwidth.log | \
awk -F'|' '{
ts = substr($1, 1, 19);
if (ts != prev_ts) {
if (NR > 1) {
printf "%s | node-a:%.1f KB/s | node-b:%.1f KB/s | node-c:%.1f KB/s\n",
prev_ts, a/1024, b/1024, c/1024;
}
a=b=c=0; prev_ts = ts;
}
if ($2 == "node-a") a += $3;
else if ($2 == "node-b") b += $3;
else if ($2 == "node-c") c += $3;
}'
三、对接 Prometheus + Grafana 实现可视化水位图
若已有 Prometheus,可借助 nginxlog-exporter 或自定义 exporter 解析该日志:
- 配置 exporter 按
$backend_id和$body_bytes_sent提取指标,暴露为nginx_upstream_bytes_total{backend="node-a"}; - Grafana 中用 PromQL 计算 1m 平均带宽:
rate(nginx_upstream_bytes_total[1m]),单位为 bytes/sec; - 叠加阈值线(如单节点上限 50MB/s),自动标红超限节点。
四、注意几个易错点
实际部署中常见疏漏:
-
$upstream_addr含端口,映射值必须完全一致(如写成"10.0.1.10"就会匹配失败); -
$body_bytes_sent是整数,但某些小响应可能为 0(如 304),不影响总量统计; - 日志路径需确保 Nginx 用户有写权限,且磁盘空间充足(建议加
logrotate按小时切分); - 若使用
gzip,$body_bytes_sent是压缩后大小,反映的是真实网络带宽,而非原始内容大小。
这样配置后,你就能看到每个节点每秒发了多少 KB 数据,哪个节点快打满、哪个长期空闲,一目了然。

















