现在很多网站在上线时都会接入 CDN,加速已经算是标配了。但不少人会发现,即使用了 CDN,缓存效果依旧不理想,源站压力并没有明显下降。其实问题往往就出在 HTTP 响应头 上。
简单来说,WEB 服务器(Nginx、Apache)给资源加的那些标头,会直接决定 CDN 到底怎么缓存。今天我想重点聊聊几个关键的标头,尤其是经常被吐槽的 ETag。
哪些标头会左右 CDN 缓存?
(1) Cache-Control
这是大哥级别的标头,基本上 CDN、浏览器都要看它的脸色行事。
public:CDN、浏览器都能缓存。
private:只让浏览器缓存,CDN 不参与。
max-age=31536000:缓存时间,这里是一年。
no-cache / no-store:完全禁止缓存。
我自己习惯在 Nginx 里这样写:
location ~ .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|otf)$ {
expires 1y;
add_header Cache-Control “public, max-age=31536000”;
}
(2) Expires
这是老一辈的方案(HTTP/1.0 标准),基本上现在就是给老浏览器看的。新环境下用 Cache-Control 就行,但写一下也无妨。
(3) ETag
这个是争议最多的。理论上很美好:给文件一个唯一标识,下次请求时比对一下,如果没变就返回 304 Not Modified。
但问题是,ETag 的生成规则有时候特别坑。比如它会把服务器的 inode 或时间戳算进去,那在多服务器、多节点的环境下,每台机器算出来的 ETag 都不一样,结果就是缓存白搭。
所以我的建议很简单:静态资源长缓存就直接关掉 ETag。该省的验证就别浪费了。Nginx 配置示例:
location ~ .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
if_modified_since off;
etag off;
}
(4) Last-Modified
这个标头更像是 ETag 的“简化版”,直接告诉你文件最后修改的时间。配合 If-Modified-Since 一起用。但它的精度只有秒级,而且文件一改时间就变,所以也会带来一些缓存失效的问题。
ETag:用还是不用?
很多新手总觉得 ETag 是必须的,其实真不是。
优点:确实能精确判断内容有没有变动。
缺点:一旦生成规则不合理,就会拖累 CDN 缓存效率。
所以我自己的做法是:
静态文件(JS、CSS、图片等) → 直接禁用 ETag,用强缓存就够了。
动态内容 → 有需要的时候才用 ETag 或 Last-Modified 来做协商缓存。










暂无评论内容