xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

浏览器 HTTP 缓存 All In One

浏览器 HTTP 缓存 All In One

强缓存 & 协商缓存

HTTP Caching

HTTP/1.1 304 Not Modified

HTTP/1.1 200 OK

https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching

https://httpwg.org/specs/rfc9111.html

304 Not Modified

304 未修改

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304

caches 类型

private caches 私有缓存

私有缓存是绑定到特定客户端的缓存——通常是浏览器缓存。
由于存储的响应不与其他客户端共享,因此私有缓存可以存储该用户的个性化响应

# cookies
Cache-Control: private

如果响应包含个性化内容并且您只想将响应存储在私有缓存中,则必须指定私有指令
请注意,如果响应具有 Authorization 标头,则不能将其存储在私有缓存(或共享缓存,除非指定公共缓存)中。

shared caches 共享缓存

共享缓存位于客户端和服务器之间,可以存储可以在用户之间共享的响应。
共享缓存可以进一步细分为代理缓存托管缓存

  1. Proxy caches / 代理缓存
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate

  1. Managed caches / 托管缓存
Cache-Control: no-store

CDN-Cache-Control

image

https://httpwg.org/specs/rfc9213.html

heuristic caching / 启发式缓存 (协商缓存)

HTTP is designed to cache as much as possible, so even if no Cache-Control is given, responses will get stored and reused if certain conditions are met.
This is called heuristic caching.

HTTP 被设计为尽可能多地缓存,因此即使没有给出 Cache-Control,如果满足某些条件,响应也会被存储重用
这称为启发式缓存

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT

<!doctype html>
…
</html>

试探性地知道,整整一年没有更新的内容在之后的一段时间内不会更新。
因此,客户端存储此响应(尽管缺少 max-age)并重复使用一段时间。
重用多长时间取决于实施,但规范建议存储后大约 10%(在本例中为 0.1 年)的时间。

Heuristic caching is a workaround that came before Cache-Control support became widely adopted, and basically all responses should explicitly specify a Cache-Control header.

启发式缓存是在 Cache-Control 支持被广泛采用之前出现的一种解决方法,基本上所有响应都应明确指定一个 Cache-Control 标头。

存储的 HTTP 响应有两种状态:fresh 和 stale;
fresh 状态通常表示响应仍然有效并且可以重用,而 stale 状态表示缓存的响应已经过期

HTTP/1.0 中,新鲜度过去是由 Expires 标头指定的。

标Expires头使用显式时间而不是通过指定经过的时间来指定缓存的生命周期。

Expires: Tue, 28 Feb 2022 22:22:22 GMT

然而,时间格式难以解析,发现了很多实现错误,并且有可能通过故意偏移系统时钟来诱发问题;
因此,在 HTTP/1.1Cache-Control: max-age 采用了—用于指定经过的时间

如果Expires 和 Cache-Control: max-age 都可用,max-age 则定义为首选(Cache-Control 优先级高)。
Expires 所以现在HTTP/1.1被广泛使用就没有必要提供了。

Vary

Vary: Accept-Language

过时的响应不会立即被丢弃。
HTTP 有一种机制,可以通过询问源服务器将陈旧的响应转换为新的响应。
这称为验证,有时称为重新验证

验证是通过使用包含 or 请求标头的条件请求来完成的。

响应中包含 ETag, 就先与 max-age 比较缓存是否已过期

  1. 没过期使用缓存;
  2. 过期了就发送带有标头 If-None-Match 的请求,询问服务端请求的资源是否被修改了;
    2.1 没被修改, 没更新,返回 304 未修改,接着使用缓存
    2.2 被修改,更新了,返回 200, 新的响应

响应中包含 Last-Modified, 就先与 max-age 比较缓存是否已过期

  1. 没过期使用缓存;
  2. 过期了就发送带有标头 If-Modified-Since 的请求,询问服务端是否有更新;
    2.1 没更新,返回 304 未修改,接着使用缓存
    2.2 更新了,返回 200, 新的响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600

<!doctype html>
…
</html>

以下响应是在 22:22:22 生成的,具有 max-age 1 小时(3600秒)的时间,因此您知道它在 23:22:22 之前是新鲜的。

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT

在 23:22:22,响应变得陈旧,无法重用缓存。因此,上面的请求显示了客户端发送带有请求标头的请求 If-Modified-Since,以询问服务器自指定时间以来是否有任何更改。

HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2022 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600

304 Not Modified如果自指定时间以来内容未更改,服务器将响应。

由于此响应仅指示“无变化”,因此没有响应主体——只有状态代码——因此传输大小非常小。

收到该响应后,客户端将存储的陈旧响应恢复为新鲜响应,并可以在剩余的 1 小时内重新使用它。

服务器可以从操作系统文件系统中获取修改时间,这对于提供静态文件的情况来说比较容易做到。
但是,存在一些问题;例如,时间格式复杂且难以解析,分布式服务器难以同步文件更新时间。

为了解决这些问题,ETag响应标头被标准化为替代方案。

响应头的值ETag是服务器生成的任意值
对于服务器必须如何生成值没有任何限制,因此服务器可以根据他们选择的任何方式自由设置值——例如正文内容的哈希值版本号

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600

<!doctype html>
...
</html>

如果该响应已过时,客户端将获取 ETag 缓存响应的响应标头的值,并将其放入If-None-Match请求标头中,以询问服务器资源是否已被修改:

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "33a64df5"

304 Not Modified如果服务器为请求的资源确定的标头值与请求中的值ETag相同,则服务器将返回。

但是,如果服务器确定所请求的资源现在应该具有不同的ETag值,则服务器将改为使用200 OK最新版本的资源进行响应。

注意:在评估如何使用 ETag 和 Last-Modified 时,请考虑以下事项:在缓存重新验证期间,如果同时存在 ETag 和 Last-Modified,则 ETag 优先。
因此,如果你只是考虑缓存,你可能会认为 Last-Modified 是不必要的。
但是,Last-Modified 不仅对缓存有用; 相反,它是一个标准的 HTTP 标头,内容管理 (CMS) 系统也使用它来显示上次修改时间,爬虫程序用来调整爬虫频率,以及用于其他各种目的。
因此考虑到整个 HTTP 生态系统,最好同时提供 ETag 和 Last-Modified。

强缓存

  • expires
  • Cache-Control
    max-age
    s-maxage
    no-cache
    no-store
    public
    private
    ...

协商缓存

  • ETag / If-None-Match
  • Last-Modified / If-Modified-Since

推荐服务端带上 Last-Modified,可以作为 blogs 等资源的最后修改时间使用

image

图解浏览器 HTTP 缓存

用户行为对浏览器缓存的影响,指的就是用户在浏览器上的不同操作,会触发不同的缓存策略, 主要有 3 种:

打开网页,地址栏输入地址
查找 disk cache 中是否有匹配, 如有则使用;如没有则发送网络请求;

普通刷新 (F5):
因为 Tab 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话), 其次才是 disk cache, 如没有则发送网络请求;

强制刷新 (Ctrl + F5):
浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache (为了兼容,还带了 Pragma: no-cache), 服务器直接返回 200 和最新内容

refs

https://www.cnblogs.com/xgqfrms/p/16023937.html

https://www.cnblogs.com/xgqfrms/p/14032702.html

https://www.cnblogs.com/xgqfrms/p/12885582.html



©xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-06-24 17:26  xgqfrms  阅读(54)  评论(1编辑  收藏  举报