HTTP的缓存机制

前言

HTTP的缓存机制,主要体现在HTTP协议头里面的几个字段——Expires、Cache-control、Last-Modified/If-Modified-Since、Etag/If-None-Match等。在移动开发中,了解HTTP的缓存对开发者来说已经必不可少。

HTTP HEAD

Expires

HTTP头中的Expires字段,告诉浏览器在Expires显示的时间前,浏览器可以从缓存中读取,而不需要再次去请求。

Cache-control

Cache-control与Expires一样,都是告诉浏览器有效期。不过它不只是设置过期时间,还可以设置很多选项:

  • no-cache指示请求或响应消息不能缓存
  • no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
  • max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
  • min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
  • max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

如上图:max-age=600,表示600s内不需要重新请求。

Last-Modified

Last-Modified:资源的最后修改时间。

如果本地缓存已经过期,即超过了max-age的缓存时间,缓存的HTTP头中存在Last-Modified,则向服务器发送带有If-Modified-Since字段的请求,后面带上Last-Modified所记录的最后修改时间。

服务器收到带有If-Modified-Since的HTTP请求,会将请求的资源修改时间与If-Modified-Since时间对比:如果这段时间没有被修改过,则返回304,告诉浏览器可以继续使用本地缓存;如果资源已经修改过了,则响应请求的资源数据,返回200 OK.

Etag

Etag:服务器应答数据的时候,生成的当前资源的唯一标识。

如果本地缓存已经过期,即超过了max-age的缓存时间,缓存的HTTP头中存在Etag,则向服务器发送带有If-None-Match字段的请求,后面带上Etag所记录的当前资源的唯一标识。

服务器收到带有If-None-Match的HTTP请求,会将请求的资源唯一标识与If-None-Match的标签的标识对比:如果这段时间没有被修改过,则返回304,告诉浏览器可以继续使用本地缓存;如果资源已经修改过了,则响应请求的资源数据,返回200 OK。

Etag与Last-Modified的区别?

HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
  • 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
  • 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器生成的对应资源的唯一标识符,能够更加准确的控制缓存。Last-ModifiedETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified

跳转、刷新、强制刷新

浏览器缓存行为还有用户的行为有关:

用户操作 Expires/Cache-control Last-Moified/Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进、后退 有效 有效
F5刷新 无效 有效
Ctrl+F5刷新 无效 无效

总结

当本地存在缓存的时候,一次请求的流程:

HTTP Cache

参考:Cache-Control section of RFC 2616