汇知百科
白蓝主题五 · 清爽阅读
首页  > 路由设置

gzip压缩如何影响缓存命中率

在配置网站路由或CDN节点时,开启gzip压缩几乎是标配操作。它能显著减少传输体积,加快页面加载速度。但很多人没意识到,gzip压缩也会悄悄改变缓存系统的运作方式,进而影响缓存命中率

同一个资源,可能变成多个缓存对象

举个例子,服务器上有一个JS文件叫app.js,大小为300KB。如果未开启gzip,所有用户请求这个文件时,缓存服务器(比如CDN节点)会统一返回同一个缓存副本。但一旦启用gzip,情况就变了:支持gzip的浏览器会带上Accept-Encoding: gzip头,而不支持的老设备可能不会带。

这样一来,缓存系统就得判断——这个请求要不要压缩版本?结果就是,app.js被缓存成了两个独立的对象:一个是原始未压缩版,另一个是gzip后的版本。它们共享同一个URL,但在缓存层里是两份数据。

缓存键的变化是关键

大多数现代缓存系统(如Varnish、Nginx Proxy Cache、Cloudflare等)在生成缓存键时,默认不包含Accept-Encoding。这意味着不同编码请求可能命中同一个缓存项,造成混乱。更合理的做法是把客户端支持的压缩方式纳入缓存键的一部分。

以Nginx为例,可以通过添加变量来区分:

gzip on;
gzip_types text/plain text/css application/json application/javascript;

proxy_cache_key "$scheme$request_method$host$request_uri$gzip_accept_encoding";

这样,当用户请求带有Accept-Encoding: gzip时,缓存键会自动包含这一信息,避免未压缩和压缩版本互相覆盖。

移动网络下的实际表现

在4G/5G环境下,很多中低端安卓机仍使用老旧浏览器,不一定完整支持gzip解压。如果你的站点主要面向这类用户,盲目开启全量gzip反而可能导致缓存碎片化——大量小众请求无法复用已有缓存,命中率下降。

一个折中方案是按用户代理或设备类型动态控制压缩:

if ($http_user_agent ~* "(Mobile|Android)") {
    gzip off;
}

当然,这种做法需要权衡流量成本和缓存效率。更好的方式是结合日志分析,看哪些客户端占比高,再决定是否对特定群体关闭压缩。

HTTPS与协商缓存的叠加效应

现在大部分站点走HTTPS,而TLS握手本身有一定开销。如果因为gzip导致缓存未命中,就得反复回源拉取资源,不仅增加延迟,还加重源站负担。尤其是API接口类内容,频繁的小数据包即使启用了Brotli或gzip,也未必省多少流量,反而让ETag和Last-Modified这些协商机制失效得更频繁。

建议对JSON、XML这类文本接口明确设置缓存策略,并确保压缩状态一致:

location ~ \.(json|xml)$ {
    add_header Cache-Control "public, max-age=3600";
    gzip on;
    proxy_cache_valid 200 1h;
}

保持压缩开关稳定,能让CDN节点更有效地复用缓存,提升整体命中率。