HTTP cache
HTTP 缓存的历史
缓存的优点
- 减少了传输数据的冗余
- 减少了带宽的占用
- 减少了服务器的开销
- 降低了时延,增加了用户效率
缓存方式
主要包括,浏览器缓存、代理服务器缓存,http协议中的强缓存和协商缓存。
浏览器缓存与HTTP缓存
缓存命中
缓存命中与否分为三种情况
- 缓存命中 cache hit - 200(memory cache, disk cache)
- 缓存未命中 cache miss - 200
- 缓存再验证 cache revalidation
再验证缓存命中 revalidation hit - 304
再验证缓存未命中 revalidation miss - 200
浏览器缓存
内存缓存:
当浏览器加载一个页面时,它会将页面中的静态资源(例如脚本、样式、图片等)缓存到内存中。这些资源可以快速加载,因为它们在内存中的访问速度比在硬盘中的快得多。内存缓存的原理是将资源加载到浏览器内存中,并在后续请求该资源时,直接从内存中读取,不再向服务器发送请求。
磁盘缓存:
当浏览器第一次加载一个页面时,它会将页面中的静态资源(例如脚本、样式、图片等)缓存到磁盘中。这些资源可以在后续访问时快速加载,因为它们已经被缓存在磁盘中。磁盘缓存的原理是将资源写入到硬盘中,并在后续请求该资源时,先从硬盘中读取,如果存在,则不再向服务器发送请求,而是直接返回缓存的数据。
二者的一个显著特点是,内存缓存的数据会随着浏览器的关闭而失效,而磁盘缓存的数据会一直保留,直到过期或者手动清除。
强缓存
- Cache-Control: max-age=xxx(s) and Expires (HTTP/1.0)
max-age 可以设置一个相对时间,而Expires 只能设置一个j绝对时间,如果同时存在,max-age 优先级高于 Expires.
使用场景是:
当设置cache-control: max-age=3600
时,在1个小时内,浏览器都会直接从缓存中读取资源,而不会向服务器发送请求。当超过一个小时时,浏览器才会向服务器发送请求,获取最新的资源。
当设置Expires: Wed, 21 Oct 2020 07:28:00 GMT
时,在2020年10月21日07:28:00之前,浏览器都会直接从缓存中读取资源,而不会向服务器发送请求。当超过这个时间时,浏览器才会向服务器发送请求,获取最新的资源。
相对来说maxage 会比expires 来的更加灵活
当资源的有效期比较短,例如一些动态资源,可以使用 max-age,当资源的有效期比较长,例如一些静态资源,可以使用 Expires。
协商缓存
服务器再验证、缓存过期.
场景是:cache-control and expires
过期时,这时不代表缓存是不能用了。而是需要向服务器发送请求,验证缓存是否可用。
- 如果验证的内容发生了变化,那么服务器会返回最新的资源,更新缓存服务器,且返回到客户端;
- 如果验证的内容没有发生改变,那么服务器会返回304,告诉客户端直接使用缓存。
使用协商缓存,通过条件缓存字段实现。
条件缓存字段
If-Modified-Since/Last-Modified and IF-None-Match/Etag
客户端通常在收到来自服务器的HTTP响应时,缓存 ETag 和 Last-Modified 头部。这些首部包含了有关服务器上资源版本信息。客户端可以用他们判断缓存的资源是否过期。
当客户端发出GET 请求并收到带有ETag 和 Last-Modified 响应头的HTTP响应时,会把这些信息缓存起来。当第二次请求相同的资源时,客户端会把这些信息放在请求头中发送给服务器。服务器会比较客户端请求头中的 ETag 和 Last-Modified 与服务器上资源的 ETag 和 Last-Modified 是否匹配。如果匹配,服务器会返回一个空的响应体,告诉客户端可以使用缓存的资源。如果不匹配,服务器会返回最新的资源,且返回到客户端。
If-Modified-Since 作为请求头的一部分,存放的是Last-Modified的缓存。当发送到服务器时,服务器回去对比If-Modified-Since和当前服务器上的实际文件的Last-Modified 是否一致,如果一致,说明文件没有修改过,直接返回304,客户端继续使用缓存文件;如果不一致,说明文件有修改,那么返回200,同时返回最新的文件内容。
同理,If-None-Match 相同的道理,只是If-None-Match 存放的是Etag的缓存。当发送到服务器时,服务器回去比对If-None-Match 和当前服务器上实际该文件的ETag 是否一致,如果一致,说明文件没有修改过,直接返回304,客户端继续使用缓存文件;如果不一致,说明文件有修改,那么返回200,同时返回最新的文件内容。
权重
source: bing.com/chat
当 If-None-Match 和 If-Modified-Since 请求头同时出现在一个 HTTP 请求中时,服务器会忽略 If-Modified-Since 请求头。这是因为 If-None-Match 请求头被认为是 If-Modified-Since 请求头的更精确替代品,两者仅为了与可能不实现 If-None-Match 的旧中间件进行互操作而组合在一起。
因此,当服务器支持 If-None-Match 时,它的优先级高于 If-Modified-Since。
Q&A
如何操作使得浏览器未命中内存缓存?
打开一个新的私密窗口:使用浏览器的私密模式,可以避免使用内存缓存,因为私密模式通常不会将任何数据缓存在内存中。禁用缓存功能:在浏览器开发者工具中,可以勾选禁用缓存选项,这样每次刷新页面都会从服务器重新获取资源,而不会使用内存缓存。
强制刷新页面:在浏览器中按下 Ctrl+F5(Windows)或 Cmd+Shift+R(Mac)键,可以强制浏览器忽略本地缓存和代理缓存,重新请求页面资源。
修改请求头:在每次请求资源时,可以通过修改请求头信息,告诉服务器不要返回缓存数据。例如,在请求头中加入 “Cache-Control: no-cache” 或 “Pragma: no-cache” 等字段,就可以避免使用内存缓存。
附录
cache-control 有哪些字段