在Nginx的变量体系中,$gzip_ratio是一个容易被忽略但非常实用的内置变量。它只在响应体经过gzip模块压缩之后才会被赋值,代表原始内容长度与压缩后内容长度的比值。很多人在做访问日志定制或带宽统计时,只知道用$body_bytes_sent看实际发出去多少字节,却不知道借助$gzip_ratio反推源站内容大小,从而评估压缩模块的真实收益。本文将从变量机制、日志实践以及常见误区三个层面,把$gzip_ratio讲清楚。

一、$gzip_ratio的底层赋值机制与取值特点
Nginx的gzip模块在过滤链中处于响应体输出阶段。当响应头确定使用gzip编码,并且内容类型匹配gzip_types配置时,模块会边收边压,在最后一个数据块发送完毕后,才能算出整体压缩比。因此$gzip_ratio并不是在请求一进来就有的,它在log阶段才稳定可用。如果某次响应因为首部已发出、来不及压缩(比如proxy缓冲关闭且后端秒回),或者内容本身小于gzip_min_length,那么该变量会保留默认值,通常是连字符或者空,具体看日志格式定义。
从精度上看,$gzip_ratio一般只保留小数点后两位,属于粗略比例。它等于原始字节数除以压缩后字节数,而不是压缩率百分比。比如原始九千字节压成三千字节,比值就是三,代表省了三分之二体积。由于计算基于整个响应体,若上游分块慢或启用了chunked,只要最终走完gzip过滤器,比值依旧准确。理解这一点,有助于在写条件判断时避免用$gzip_ratio做过早分流,它不适合出现在server块重写里,而更适合出现在log_format与镜像上报中。
另外要注意,当同时开启gzip_static,也就是优先发送预压缩的.gz文件时,$gzip_ratio依旧会根据实际发送文件大小与内存中记录的原始大小来填。如果运维手动删了源文件只留gz,Nginx无法得知原大小,变量可能异常。所以依赖该变量做长期报表的场景,务必保证源文件与gz成对存在,或者改用应用层埋点补充原长字段。
二、将$gzip_ratio写入日志格式做压缩效率分析
最常见的用法是在http段定义log_format时加入这个变量。下面示例展示了如何组合使用$body_bytes_sent与$gzip_ratio,让每条日志都带有压缩倍数信息:
http {
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'gzip_ratio=$gzip_ratio';
access_log /var/log/nginx/access.log compression;
}
有了上面的配置,运维可以直接用awk把高于某比值的请求筛出来,看哪些接口文本收益大。比如下面这段shell思路,统计平均压缩比:
awk '{split($NF, a, "="); sum+=a[2]; n++} END {print sum/n}' /var/log/nginx/access.log
在实践中,把$gzip_ratio和$content_type一起记录会更直观。文本、JSON、XML通常能到二到四倍,而已经压缩过的图片、视频则接近一。若发现本该高比的API返回接近一,就要检查是不是gzip_types漏配,或者后端自己先压了一次导致Nginx识别为不可压。通过长期日志对比不同路由的压缩比曲线,还能在升级Nginx或调整gzip_comp_level后,量化带宽变化,而不是凭感觉。
三、使用$gzip_ratio时的典型误区与替代方案
第一个误区是以为$gzip_ratio能用于if条件动态关闭压缩。由于变量在日志阶段才可靠,在access阶段做if判断会得到空值,导致逻辑失效。正确做法是依靠gzip_min_length、gzip_types等静态指令控制范围,把$gzip_ratio纯粹当作观测值。第二个误区是拿它算精确节省带宽,因为小数精度与边界请求会让总和偏移,做财务报表前应与交换机镜像流量交叉验证。
如果业务需要更细的压缩元数据,比如分块压缩比或按字段压缩,Nginx原生变量就不够用了。此时可以在应用代码里用zlib自己算,并写进响应头,例如X_Compress_Ratio,再用$upstream_http_x_compress_ratio记录。另一种思路是用ngx_lua在log阶段读取ngx.var.gzip_ratio并推到消息队列,做近实时看板。下面的Lua片段演示了读取并打点:
log_by_lua_block {
local r = ngx.var.gzip_ratio
if r and r ~= "-" then
-- 推送到内部统计服务
ngx.timer.at(0, function(premature)
-- 省略具体http调用
end)
end
}
总的来说,$gzip_ratio是一个低成本高回报的观测变量。只要避开在过早阶段引用它,并接受其精度限制,就能用极小的配置代价,把压缩效果从黑盒变成可量化指标。配合日志采集系统,中小团队也能拥有媲美商业CDN的压缩报表能力。
Nginxgzip_ratio日志分析修改时间:2026-08-16 06:56:28