浏览器 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
共享缓存
共享缓存位于客户端和服务器之间,可以存储可以在用户之间共享的响应。
共享缓存可以进一步细分为代理缓存
和托管缓存
。
- Proxy caches / 代理缓存
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
- Managed caches / 托管缓存
Cache-Control: no-store
CDN-Cache-Control
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.1
中 Cache-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
比较缓存是否已过期
- 没过期使用缓存;
- 过期了就发送带有标头
If-None-Match
的请求,询问服务端请求的资源是否被修改了;
2.1 没被修改, 没更新,返回 304 未修改,接着使用缓存
2.2 被修改,更新了,返回 200, 新的响应
响应中包含 Last-Modified
, 就先与 max-age
比较缓存是否已过期
- 没过期使用缓存;
- 过期了就发送带有标头
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 等资源的最后修改时间
使用
图解浏览器 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, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16408499.html
未经授权禁止转载,违者必究!