乐趣区

http缓存详细分析

每天系统复习一个知识点
http 缓存
http 缓存主要分为了两类 强缓存 (本地缓存) 和协商缓存
浏览器在请求某一资源时,会先获取改资源缓存的 header 信息,判断是否命中强缓存(expires 的信息和 cache-control)若命中直接从缓存中获取该资源信息,包括缓存 header 信息,本次请求根本就不会与服务器进行通信。此为强缓存(本地缓存)
如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的的有关缓存的 header 字段信息(last-modified/if-modified-since 和 Etag/if-none-Match), 由服务器根据请求中相关 header 信息来比对结果是否协商缓存命中,若命中,则服务器返回新的响应 header 信息更新缓存中的对应 header 信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取,否则返回最新的资源内容。
获取资源形式 状态码 发送请求到服务器
强缓存 从缓存取 200(from cache)否,直接从缓存取协商缓存 从缓存取 304(not modified)是,正如其名,通过服务器来告知缓存是否可用
强缓存相关的 header 字段
1 expires, 这是 http1.0 的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,如 Mon, 10 Jun 2015 21:31:12 GMT。如果发送请求的时间在 expires 之前,那么本地缓存始终有效,否则就会发送请求到服务器来获取资源。
2 cache-control:max-age=number,这是 Http1.1 时出现的 header 信息。主要是利用该字段的 max-age 值来进行判断。它是一个相对值,资源第一次的请求时间和 cache-control 设定的有效期,计算出一个资源过期时间。再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行,cache-control 除了该字段外,还有下面几个比较常用的设置值。no-cache : 不使用本地缓存,需要使用协商缓存。no-store : 直接禁止浏览器缓存数据。(强缓存和协商缓存都不行),每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。(常用于银行等重要业务)public : 可以被所有的用户缓存,包括终端用户和 cdn 等中间代理服务器 private : 只能被终端用户缓存,不允许 CDN 等中继缓存服务器对其缓存
注意:如果 cache-control 与 expires 同时存在的话,cache-control 的优先级高于 expires。

协商缓存
协商缓存都是由服务器来确定缓存资源是否可用的,所以客户端与服务器端通过某种标识进行通信,从而让服务器判断请求资源是否可以缓存访问,这里涉及到下面两组 header 字段。这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段(last-modified 或者 ETag), 则后续请求则会带上对应的请求字段(if-modified-since 或者 if-none-match),若响应头没有 last-modified 或者 Etag 字段,则请求头也不会有对应的字段。
1, 第一次和服务器交互,服务器返回资源 在 response 的 header 加上 last-modified 的 header. 这个 header 表示这个资源在服务器上的最后修改时间
2, 第二次请求这个资源,浏览器会在 request header 加上 if-modified-since 的 header. 这个 header 的值就是上一次请求时返回的 last-modified 的值。服务器再次收到资源请求。根据浏览器传过来的 if-modified-since 和资源在服务器上的最后修改时间判断资源是否有变化,如果没有发生变化则返回 304 not modified . 但是不会返回资源内容。如果有变化,就正常返回资源内容和更新 last-modified 字段。当服务器返回 304 not modified 的响应时,response header 中不会再添加 last-modified 的字段。因为既然资源没有变化,那么 last-modified 也就不会改变.
Etag/if-none-Match 这两个值是由服务器生产的每一个资源的唯一标识字符串,只要资源有变化就这个值就会改变,其判断过程和 last-modified/if-modified-since 类似,与 last-modified 不一样的是。当服务器返回 304 notmodified 的响应 response header 中还会把这个 etag 返回,即使这个 eTag 跟之前没有变化。
**Etag 比较的是文件资源的特征值,而 Last-Modifield 则比较的是文件资源的最后的修改时间。这两个其实是相辅相成的,不是有了 Etag 就不该有 Last-Modifield,有了 Last-Modifield 就不该有 Etag,同时传入服务器时,服务器会根据自己的缓存机制进行选择要使用哪个,甚至可以两个都进行参考
比如 img 肯定判断 last-modified 更方便。其他文件可能比较 etag 更方便 **
既生 last-modifed 何生 ETag
你可能会觉得使用 last-modified 已经足以让浏览器知道本地的缓存副本是否足够新,为什么还要 Etag 呢。http1.1 etag 的出现主要是为了解决几个 last-modifed 比较难解决的问题:
1 一些文件也行会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET;
2 某些文件修改非常频繁,比如在秒以下的时间内进行修改(比方说 1s 内修改 N 次)if-modified-since 能检查到的粒度是 s 级的,这种修改无法判断(unix 记录 mtime 只能精确到秒)
3 某些服务器不能精确得到文件的最后修改时间。
不能缓存的请求

退出移动版