需通过nginx日志记录$bytes_sent与$body_bytes_sent,用map构造伪$gzip_ratio,再经prometheus/loki解析计算压缩率并设阈值告警,同时关联诊断压缩配置、请求头、预压缩文件及上游压缩等根因。

直接在 Nginx 中监控 gzip 压缩率并实时告警异常波动,不能靠内置变量(Nginx 本身不暴露压缩率数值),必须通过日志 + 外部可观测性系统组合实现。核心思路是:让 Nginx 记录原始大小与压缩后大小 → 在日志中结构化提取 → 用 Prometheus 或 Loki 实时计算压缩率 → 设置阈值触发告警。
一、Nginx 日志中记录压缩前后大小
需启用 gzip_vary on 和 gzip_static on,并在自定义日志格式中加入两个关键变量:
-
$bytes_sent:实际发送给客户端的字节数(含 gzip 后大小) -
$body_bytes_sent:响应体原始字节数(未压缩前,不含响应头)
示例日志格式配置(在 http 块中):
' "$request" $status $bytes_sent '
' $body_bytes_sent "$http_referer" "$http_user_agent" '
' "$gzip_ratio"';
注意:$gzip_ratio 是一个伪变量——Nginx 不原生支持它,但可通过 map 指令动态计算并注入:
default "";
~^([1-9][0-9]*):([1-9][0-9]*) "$1/$2";
}
该 map 将原始大小与发送大小拼成形如 "12345:2345" 的字符串,并保留为可解析格式(后续由日志处理器计算比值)。
二、采集日志并结构化解析压缩率
推荐使用 Prometheus + nginxlogexporter 或 Loki + Promtail 方案:
- 用 Promtail 提取
$body_bytes_sent和$bytes_sent字段,作为标签或指标上报 - 在 Loki 中用 LogQL 提取数值:
| json | line_format "{{.body_bytes_sent}} {{.bytes_sent}}" | regexp `(d+) (d+)` | unwrap _entry - 在 Prometheus 中,通过
nginxlogexporter将每条日志转为两个浮点指标:nginx_log_body_bytes{path="/js/app.js"}和nginx_log_bytes_sent{path="/js/app.js"}
然后定义压缩率指标(PromQL 示例):
1 - rate(nginx_log_bytes_sent_sum[5m]) / rate(nginx_log_body_bytes_sum[5m])该表达式近似反映 5 分钟窗口内平均压缩率(注意:仅对非零、非 304/206 等特殊响应有效,需加过滤)。
三、设置压缩率波动告警规则
压缩率本身不是越高压越好——过高(>95%)可能意味着内容过小或压缩冗余;过低(
- 对静态资源路径(
/js/.*.js$,/css/.*.css$)单独计算 P90 压缩率 - 当 5 分钟内压缩率标准差 > 0.15,且均值偏离历史基线 ±20%,触发预警
- 当某类资源(如 .json)压缩率突然跌至 gzip off 被误配)
Prometheus 告警示例(Alertmanager 规则):
- alert: GzipCompressionRateDropexpr: |
stddev_over_time((1 - rate(nginx_log_bytes_sent_sum{path=~"/js/.*\.js"}[5m])
/ rate(nginx_log_body_bytes_sum{path=~"/js/.*\.js"}[5m]))[1h:]) > 0.18
for: 3m
labels:
severity: warning
annotations:
summary: "JS resource gzip compression rate highly unstable"
四、关联诊断与根因定位
告警触发后,需快速判断是配置、内容还是环境问题:
- 检查
gzip_types是否漏配 MIME 类型(如新增了.webp但未加入白名单) - 确认请求头含
Accept-Encoding: gzip,且响应头返回Content-Encoding: gzip(可用curl -I验证单点) - 排查是否命中预压缩文件(
.gz)而跳过实时压缩逻辑——此时$body_bytes_sent为 0,会导致除零错误或压缩率失真,需在 map 中排除 - 验证上游是否已压缩(如后端 Java 应用启用了 response 压缩),导致 Nginx 不再处理
建议在告警注释中自动附带 curl 命令模板和常见检查项链接,缩短 MTTR。











