Gzip是否成瓶颈需通过三级对照实验实测:先关压缩测CPU基线,再开常规压缩,最后高压缩,对比各worker的CPU曲线与$request_time、$upstream_response_time变化;若高压缩阶段CPU跃升且$request_time拉长而$upstream_response_time不变,即可确认压缩为瓶颈。

直接看 CPU 和响应时间的对应关系,而不是只盯着“高并发”或“开了 Gzip”就下结论。真正卡顿往往不是连接数不够,而是压缩在 worker 进程里实时算,把 CPU 吃满,拖慢了整个事件循环。
Gzip 压缩是否真成瓶颈,得做三级对照实验
不能靠猜,要实测压缩对 CPU 的实际影响:
- 第一步:关闭所有压缩(
gzip off; brotli off;),用 wrk 对固定接口压测 5 分钟(比如 200 QPS、响应体 ≥2KB),记录各 worker 的 CPU 使用基线; - 第二步:开启常规 Gzip(按安全配置,
gzip_min_length 1024、排除图片等格式),保持相同流量再跑 5 分钟; - 第三步:切换为高压缩(如
gzip_comp_level 9或启用 Brotli level 6),流量不变,再跑 5 分钟。
每次 reload 后等 10 秒再开始计时,确保连接平稳。对比三条 CPU 曲线——如果某个 worker 在高压缩阶段 CPU 显著跃升,同时它的 $request_time 拉长,但 $upstream_response_time 几乎不变,那基本就是压缩在拖后腿。
避开 Gzip 配置常见坑,别让优化变负优化
宝塔或手动配 Gzip,容易漏掉关键项,导致白开还伤性能:
-
gzip_vary on必须加,否则 CDN 或代理可能缓存未压缩版本,造成内容错乱; -
gzip_min_length别设成 1,小响应(比如 20 字节 JSON)压缩后反而更大,纯耗 CPU,建议设为1024; - 明确禁用对已压缩格式的二次压缩:
gzip_disable "msie6\|\.jpg\|\.jpeg\|\.png\|\.gif\|\.webp";,避免无谓计算。
确认是不是压缩问题,先排除其他干扰项
CPU 高 ≠ 一定是压缩惹的祸,也可能是系统或配置层面的隐性瓶颈:
- 检查
worker_rlimit_nofile和系统ulimit -n是否匹配,文件描述符不足会触发阻塞,表现像 CPU 高但响应慢; - 确认没加载冗余模块(尤其是未使用的第三方 filter),它们可能悄悄吃 CPU;
- 观察
sendfile是否开启、gzip_buffers是否足够——缓冲区太小会导致多次内存拷贝,CPU 升高但$upstream_response_time不变; - 如果 CPU 高但
$request_time很短,可能是大量短连接反复建连/断连,此时重点查客户端行为和keepalive_timeout设置。
更彻底的解法:把压缩移出请求路径
动态压缩本质是拿 CPU 换带宽,高并发下得不偿失。真正稳的方案是预压缩:
- 静态资源(JS/CSS/HTML/WASM)在构建阶段就生成
.br和.gz文件; - Nginx 配置用
try_files $uri.br $uri.gz $uri =404;,命中即发,零运行时 CPU 开销; - 动态内容(如 API 返回 JSON)只开轻量级 Brotli(
brotli_comp_level 2),且仅限text/html、application/json等类型; - 务必加
add_header Vary Accept-Encoding;和Content-Encoding响应头,否则浏览器或 CDN 不认。
验证是否生效,别信配置,要看真实请求:用 curl 或 Chrome DevTools 检查 Response Headers 里有没有 Content-Encoding: br 和 Vary: Accept-Encoding,再对比 TTFB 和 CPU 占用变化。


















