统计静态资源压缩率需依托nginx的$gzip_ratio变量,通过自定义log_format记录该值,过滤非“-”样本后按路径或mime类型分组计算平均值,并结合$body_bytes_sent反推原始大小与实际节省量。

直接计算压缩率不难,但把它用在告警逻辑里容易出错——关键不在“怎么算”,而在“什么时候算、对谁算、算完怎么用”。
用 compress/gzip 压缩单文件时如何获取压缩率
压缩率 = (原始大小 − 压缩后大小) / 原始大小。必须等 gzip.Writer.Close() 执行完才能拿到真实压缩后大小,否则 os.Stat() 读到的是未刷新的临时尺寸。
- 先
os.Stat(src)拿原始大小srcSize - 用
gzip.NewWriter写入目标文件,写完必须调writer.Close() - 再
os.Stat(dst)拿压缩后大小dstSize,此时才是最终体积 - 压缩率 =
float64(srcSize-dstSize) / float64(srcSize)(注意类型转换)
压缩率告警不能只看单次结果
日志文件每分钟生成一个,每次压缩率波动很大:空日志可能压到 99%,带调试信息的日志可能只有 40%。如果对每个文件都按“压缩率
- 真正该监控的是“连续 N 个文件压缩率低于阈值”,比如最近 5 个 .log.gz 文件平均压缩率
- 或改用“压缩后大小 / 原始大小 > 3.0”,即膨胀了——说明源文件可能已被加密或损坏
- 记录每个文件的
srcSize和dstSize到本地 SQLite 或内存 map,避免反复 stat
用 archive/zip 打包目录时压缩率怎么算
ZIP 不是纯压缩格式,它包含文件头、目录结构、可选加密等开销。直接用总原始大小除总压缩大小会偏低——尤其当打包大量小文件时,ZIP 头部占比明显上升。
- 不要用
zip.File.FileInfo().Size()当原始大小,那是 ZIP 包内单个文件的声明大小,可能和磁盘上不一致 - 正确做法:遍历源目录,累加
os.Stat().Size()得到真实原始总大小 - ZIP 包本身大小用
os.Stat(zipPath).Size(),但需确认写入完成且已 close*zip.Writer - 若发现压缩率突然从 70% 掉到 10%,优先检查是否误把二进制文件(如 PDF、图片)混进日志目录
压缩率异常背后常被忽略的根因
压缩率低 ≠ 配置错了。更可能是数据本身变了,而你没意识到。
- 日志框架升级后默认加了 traceID 字段,导致文本重复率下降,gzip 效果变差
- 用户上传的附件类型变了:原来全是纯文本 CSV,现在混入 base64 编码的图片字符串
- 备份脚本里用了
tar -c | gzip,但某天改成tar -czf后没注意 gzip 级别被重置为默认BestSpeed,压缩率暴跌 - 监控脚本自己跑在容器里,挂载的宿主机路径权限受限,
os.Stat()返回错误却被静默忽略,导致压缩率算成 NaN
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











