HTTP缓存介绍

当网站加载的资源越来越多时,为资源添加浏览器缓存是明智的举措。可以通过HTTP响应头中设定相应的信息,告诉浏览器以什么样的形式缓存,以及缓存多久。

Caching in HTTP/1.0

Expires

在HTTP/1.0的时代,可以通过Expires实现简单的缓存机制。比如:

1
Expires: Thu, 01 Dec 1994 16:00:00 GMT

表示该资源将在1994年12月1号16点过期,显然该资源已经过期。任何无效数字或者已过期的时间都会导致资源过期。

注意:其中GMT表示格林威治标准时间,不允许修改,这是HTTP标准的要求。

Pragma

Pragma用于指示是否允许资源缓存。

1
Pragma: no-cache

If-Modified-Since和Last-Modified

缓存虽好,但需要保证缓存的实时性,服务器更新资源时,浏览器需即刻下载最新的资源。

Last-Modified是响应头信息,服务器可以将资源的最近修改时间写入响应头,下次浏览器请求该资源时,将携带If-Modified-Since请求头,如果资源在If-Modified-Since之前没有修改过,将返回304和空响应体。

注意:负载均衡要保证各服务Last-Modified时间一致。

Caching in HTTP/1.1

Cache-Control

最重要的缓存头,现代的浏览器都支持,一般只需要设置Cache-Control就够了。

例如:

1
Cache-Control:public, max-age=31536000
指令说明
no-cache必须先与服务器确认资源是否有变化,如果资源未发生变化,则可避免下载
no-store禁止浏览器以及中间缓存存储任何数据,每次都要向服务器发起请求
public不仅可以被浏览器缓存,还可以被中间的代理缓存,如CDN
private不允许任何中间缓存对其缓存
max-age从请求的时间开始,允许获取响应被重用的最长时间

定义最佳 Cache-Control 策略

http-cache-decision-tree

理想情况,应该尽可能缓存更多资源,缓存更长时间,并且为每个响应提供验证令牌,以实现高效的重新验证。

注意:现代浏览器,Cache-Control会覆盖Expires。

ETags

和Last-Modified都是用于验证资源是否过期,Last-Modified基于修改时间,ETags则通过对比资源内容是否修改。

例如响应头中携带资源的md5标识:

1
2
Cache-Control:public, max-age=31536000
ETag: "15f0fff99ed5aae4edffdd6496d7131f"

在接下来的请求将携带请求头信息:

1
If-None-Match: "15f0fff99ed5aae4edffdd6496d7131f"

只要当前资源的ETag仍然是If-None-Match的值,就直接返回304和空响应体。

注意:负载均衡要注意保证各实例ETag一致。

参考链接:
http://www8.org/w8-papers/5c-protocols/key/key.html
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers