HTTP 缓存策略----强缓存、协商缓存

423 阅读7分钟

缓存

image.png

HTTP 缓存分为 2 种,一种是强缓存,另一种是协商缓存。主要作用是可以加快资源获取速度,提升用户体验,减少网络传输,缓解服务端的压力。

浏览器是如何判断是否使用缓存:

  • 第一次请求:

image.png

  • 第二次请求相同网页:

image.png

强缓存:

浏览器在加载资源时不会向服务器发出请求,直接从缓存读取资源。

返回Status Code:200(from disk cache)或者返回Status Code:200(from memory cache)

两者区别:

  • Status Code:200(from memory cache)不访问服务器,一般已经加载过该资源并且缓存在内存中,直接从内存中读取缓存,关闭浏览器,数据不存在。再次打开时,则不会出现from memory cache。
  • Status Code:200(from disk cache )不访问服务器,已经在之前的某个时间加载过该资源,直接从硬盘中读取缓存,关闭浏览器,数据依然存在

优先访问memory cache,其次是disk cache

强缓存的header参数:

  • expires 表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回.

  • Cache-Control: HTTP1.1新增的属性,主要利用该字段的max-age值进行判断,是相对值。(资源第一次请求时间和Cache-Control设定有效期,计算出一个资源过期时间,在拿这个过期时间跟当前的请求时间比较)常用的属性值有:

    • max-age:单位为秒,缓存时间计算方式是距离发起的时间的秒数
    • no-cache:不使用强缓存,需要与服务器验证缓存是否是最新
    • no-store:禁止缓存,每次都向服务器请求最新的资源
    • private:专用于个人的缓存
    • public:响应可以被中间代理、CDN等缓存
    • must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证

协商缓存:

强缓存失效后,浏览器一定会发送一个请求到服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源.

强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:

协商缓存生效,返回304和Not Modified

协商缓存失效,返回200和请求结果

如果前面两者都没有命中,直接从服务器加载资源

协商缓存header的参数:

  • ETag/If-None-Match(这两个值是由服务器生成的每个资源的唯一标识符,资源有变化,值就会改变)

当资源过期时,浏览器发现响应头里有Etag,则再次向服务器请求时带上请求头if-none-match(值时Etag的值)。服务器收到请求进行比对,决定返回200或304

ETag/If-None-Match 的值是一串 hash 码,代表的是一个资源的标识符,当服务端的文件变化的时候,它的 hash码会随之改变,通过请求头中的 If-None-Match 和当前文件的 hash 值进行比较,如果相等则表示命中协商缓存。ETag 又有强弱校验之分,如果 hash 码是以 "W/" 开头的一串字符串,说明此时协商缓存的校验是弱校验的,只有服务器上的文件差异(根据 ETag 计算方式来决定)达到能够触发 hash 值后缀变化的时候,才会真正地请求资源,否则返回 304 并加载浏览器缓存。

  • Last-Modified(用于标记请求资源的最后一次修改时间。)/If-Modified-Since(是一个条件式请求首部,与Last-Modified何用,上次返回的Last-Modified的值)

last-Modified:浏览器向服务器发送资源最后的修改时间

Last-Modified/If-Modified-Since 的值代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存。

强缓存与协商缓存的区别

image.png

相同点:

如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据。

不同点: 强缓存不发请求到服务器,协商缓存会发请求到服务器。

额外信息:304状态:未修改(客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码)

通俗易懂总结

缓存步骤如下:

  • 首先浏览器发出Http请求,浏览器发现本地已有所请求资源的缓存,便开始检查缓存是否过期。有两个http头部字段控制缓存的有效期:Expires和Cache-Control
    • 查看缓存是否有Cache-control的max-age指令
      • ,则使用响应报文生成时间获取过期时间,与当前时间进行对比
      • 没有,则比较Expires中的过期时间与当前时间对比

      若缓存未过期,返回状态码200,直接从本地读取缓存。如果缓存过期,则进入协商缓存或服务器返回新资源过程。

    • 与服务器协商,此时浏览器回判断缓存中是否有Etag或Last-Modified协商缓存字段
      • ,则在请求头中添加If-None-Match,If-Modified-Since字段发送请求,然后服务器接收后判断缓存是否还可继续使用
        • 服务器只要比较If-None-Match和Etag内容是否一致,内容一致,缓存仍然可用,则返回304。然后读取缓存,页面呈现
        • 不可使用,那么就会返回200和最新的资源,然后页面呈现
      • 如果没有,则发起Http请求,服务器根据请求返回最新的资源,页面呈现

额外提示

  • 强缓存

    • Expires

    代表缓存资源的过期时间。

    • Cache-Control:

    工作原理和expires一样,两个字段同时使用,以cache- control为准

  • 协商缓存

    • Etag:

    服务器响应请求时,告诉浏览器当前资源在浏览器的唯一标识

    • Last-Modified:

    服务器响应请求时,告诉浏览器资源最后的修改时间

    • If-None-match:

    再次请求服务器时,通过此字段通知服务器客户端缓存数据的唯一标识。

    • If-Modified-Since:

    浏览器再次请求资源时,浏览器通知服务器,上次请求时,返回的资源最后修改时间

协商缓存两种方式

  • 第一种Last-modified和If-Modified-Since

1:第一次访问请求时,服务器会返回一个最后修改时间Last-modified给浏览器。

2:当浏览器再次请求时,会在request的header上附加一个If-Modified-Since的header。值为上次请求返回的Last-Modified的值。

3:服务器拿着浏览器发送过来的If-Modified-Since与服务器上的最后修改时间进行比对

若相同,说明资源是最新的,没有改动,返回304,浏览器读取本地缓存

若不相同,说明资源被修改了,返回200,服务器返回最新的资源

  • 第二种Etag和If-None-Match

与第一种不同的是:服务器返回304时,不会返回最新的Last-Modified,但是会返回新的Etag. Last-Modified可以和Etag一起使用,服务器会优先验证Etag

既然有Last-Modified,为啥还要用Etag

http1.1中Etag主要解决几个Last-Modified难解决的问题:

  • 一些文件也许会周期性的改变,但是内容并不改变。
  • 某些文件修改频繁,If-Modified-Since能检查的粒度是S级的,这种修改无法判断
  • 某些服务器不能精确的得到文件的最后修改时间 总结: 利用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或开发者生成的对应资源在服务器端的唯一标识符