# HTTP缓存
Web
缓存通过复用以前获取的资源,减少等待时间和网络流量,减少了显示资源表示形式所需的时间,可以显著提高网站和应用程序的性能。通过使用HTTP
缓存,可以使网站的响应更加敏捷。
但是,缓存也需要合理配置,因为并不是所有资源都是永久不变的。重要的是,对一个资源的缓存应截止到其下一次发生改变(即不能缓存过期的资源)。
缓存可分为私有与共享缓存两类:
- 共享缓存存储的响应能够被多个用户使用,例如网关缓存、
CDN
、反向代理缓存和负载均衡器等。 - 私有缓存只能用于单个用户,例如浏览器缓存(
Brower Caching
)。
HTTP
缓存只应该缓存GET
请求,因为其是幂等的。
# 缓存规则
按照缓存规则,缓存可以分为强制缓存和协商缓存两类:
强制缓存是指当缓存数据库中已有所请求的数据时,直接从缓存数据库中获取数据。只有缓存数据库中没有所请求的数据时,才会从服务端获取数据。
协商缓存又称对比缓存,客户端会先从缓存数据库中获取到一个缓存数据的标识,然后请求服务端验证是否失效(新鲜),如果没有失效服务端会返回304
,此时客户端直接从缓存中获取所请求的数据,如果标识失效,服务端会返回更新后的数据。
两类缓存机制可以同时存在,强制缓存的优先级高于协商缓存,当执行强制缓存时,如若缓存命中,则直接使用缓存数据库数据,不在进行缓存协商。
# 缓存控制
缓存相关的规则信息包含在header
中,具体如下:
# 强制缓存
对于强制缓存,服务器响应的header
中可以用以下两种方式表明过期时间:
Expires
:服务端返回的数据到期时间。当再次请求时的请求时间小于返回的此时间,则直接使用缓存数据。Expires
属于HTTP 1.0
协议,但由于服务端时间和客户端时间可能有误差,会导致缓存命中的误差,现在大多数使用Cache-Control
替代。
Cache-Control
:Cache-Control
有很多属性,不同的属性代表的意义也不同。max-age=t
可用来指定时间,表示t秒之后缓存内容将失效。
当在Cache-Control
中设置了max-age
时,Expires
将会被忽略。
# 协商缓存
协商缓存需要进行对比判断是否可以使用缓存。
Last-Modified
浏览器第一次请求数据时,服务器会将最后修改时间以Last-Modified: <date>
响应首部的形与数据一起发送给客户端。
当需要对缓存进行在验证时,浏览器会将该最后修改时间放到If-Modified-Since
请求首部中,发送给服务器。服务器会将此时间与服务器上请求资源的最后修改时间进行对比,如果一致则返回一个304 Not Modified
响应。304
的响应头也可以同时更新缓存文档的过期时间。否则返回带有新数据的状态为200
的响应。
另外还有一个If-Unmodified-Since
请求首部,意思为,当数据没有被修改时,返回数据。否则返回一个412 Precondition failed
的响应。
对于Last-Modified
而言,如果一个资源被修改的,但是实际内容根本没发生改变,会因为Last-Modified
时间匹配不上而返回了整个实体给客户端。因此,Last-Modified
又被称为弱校验。
ETag
为了解决Last-Modified
问题,HTTP 1.1
推出了被称为实体标签ETag
强校验。
ETag
是附加到文档上的任意标签(引用字符串),可能包含了文档的序列号或者版本名,或者是文档内容的校验及其他指纹信息。
与Last-Modified
类似,服务器响应请求时,通过此字段告诉浏览器当前资源在服务器生成的唯一标识(生成规则由服务器决定)。
再次请求服务器时,浏览器会将ETag
的值放到If-None-Match
请求首部中。服务器会将此值与被请求资源的唯一标识进行对比。相同返回304 Not Modified
,不同返回带有新的资源内容的200
的响应。
ETag
的缺点就是其值是使用算法得出的,会占用服务端计算的资源。
# Cache-Control
HTTP/1.1
定义了Cache-Control
请求首部来区分不同的缓存策略,请求首部和响应首部都支持。
Cache-Control: no-store
,禁止缓存。缓存中不会存储任何关于客户端请求和服务端响应的内容Cache-Control: no-cache
,缓存但重新验证。每次有请求发出时,缓存会将此请求发到服务器,以验证请求中所描述的缓存是否过期,若未过期才使用本地缓存副本。Cache-Control: public
公共缓存或Cache-Control: private
私有缓存。公共缓存可以被任何中间人(比如中间代理、CDN等)缓存。私有缓存表示该响应是专用于某单个用户的,中间人不能缓存此响应,只能应用于浏览器私有缓存中。Cache-Control: max-age=<seconds>
。表示资源能够被缓存(保持新鲜)的最大时间Cache-Control: must-revalidate
。在事先没有跟原始服务器再验证的情况下,不能提供这个对象的陈旧副本,但缓存可以提供新鲜副本。如果在进行must-revalidate
新鲜度检查时,原始服务器不可用时要返回504 Gateway Timeout
错误
# 不同刷新的请求执行过程
- 浏览器地址栏中写入URL,回车浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)
F5
,就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器就胆胆襟襟的发送一个请求带上If-Modify-Since
。Ctrl+F5
告诉浏览器,你先把你缓存中的这个文件给我删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作.
参考资料:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ
https://juejin.cn/post/6844903517702848526#heading-1