HTTP缓存

HTTP缓存

内容参考自MDN,我进行了一些简单的归纳和自己的一些理解

缓存的类型

缓存能够将你浏览的网页数据进行保存,当你下次再次浏览该网页时就能将上次缓存的数据拿来直接用,有什么好处呢,大家应该都能想得到,可以缓解服务端的压力,减少获取资源的时间,用户体验也可以直线上升。照这么说,那我是不是把该网站的所有页面都缓存下来,那不是很爽?理论上是可以这么做的,但是网页不是一成不变的,哪些该缓存,哪些不用缓存就决定了这个网站的体验。
缓存大致可以分成两个类型:私有缓存和共享缓存。
在这里插入图片描述私有缓存:顾名思义,私有缓存就是浏览器本地的缓存,私有缓存可以为浏览器提供向前导航,向后导航、保存网页、查看源码等功能。
共享缓存:在浏览器和服务器中间加了一个代理服务器,浏览器先向这个代理服务器发起请求,经过处理后(权限验证、缓存匹配等)再转发给源服务器,他与私有缓存的区别就是他是为大量的用户提供服务,一些比较基础或者热门的资源就会被重复使用,减少网络拥堵和延迟。
CDN缓存:CDN(Content delivery networks)缓存,也叫网关缓存、反向代理缓存。CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存没法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来说,本文讨论浏览器和服务器之间的缓存机制,在这种架构下同样适用。

缓存控制头部信息

禁止进行缓存

禁止存储任何关于客户端请求和服务端响应的内容,每次客户端发起请求都会下载完整的响应内容

Cache-Control: no-store
Cache-Control: no-cache, no-store, must-revalidate

强制确认缓存

当请求头部如下定义时,服务端会验证请求中描述的缓存是否过期,如果没有过期则返回304,然后继续使用本地的缓存而不进行更新

Cache-Control: no-cache

缓存时间

单位是秒,通过设置该字段类决定缓存的有效时间

Cache-Control: max-age=333333

缓存验证确认

告诉缓存,我给你准备了一些关于新鲜度的信息,在表现的时候要严格遵循之。HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,相对于告诉缓存,你丫必须严格遵循我的规则。

Cache-Control: must-revalidate

缓存新鲜度

新鲜度的意思其实就是缓存在浏览器中保存的时间,理论上来说,缓存可以被永久的保存在浏览器中,但是资源会变啊,我总不能一直使用原来的缓存吧,所以为了避免这种情况,就得定时的删掉那些旧的缓存并把它替换成新的缓存才行。所以浏览器会服务端会共同制定一个过期时间,当这个时间一过,这个缓存就被看作是过期的,客户端请求发出的时候,发现这个缓存过期了,它就会在请求中加一个If-None-Match头,服务器看到这个信息,就知道客户端是要我看看这个过期的缓存和新的资源相比有没有变化,服务端发现没有变化,那就返回一个304,告诉客户端:你别更新缓存了,和以前的没变化。可能大家会奇观,如果服务器更新了东西直接告诉客户端这个东西更新了不是更方便吗,的确,但是HTTP是C/S模式,服务端不能向客户端主动发起请求,所以才需要这么一个约定。
在这里插入图片描述
对于含有特定头信息的请求,会去计算缓存寿命。比如Cache-control: max-age=N的头,相应的缓存的寿命就是N。通常情况下,对于不含这个属性的请求则会去查看是否包含Expires属性,通过比较Expires(Expires响应头是一个时间,代表过了这个时间响应过期,0代表时间资源已过期)的值和头里面Date属性的值来判断是否缓存还有效。如果max-age和expires属性都没有,找找头里的Last-Modified信息。如果有,缓存的寿命就等于头里面Date的值减去Last-Modified的值除以10(注:根据rfc2626其实也就是乘以10%)。

缓存验证

用户点击刷新按钮时会开始缓存验证。如果缓存的响应头信息里含有"Cache-control: must-revalidate”的定义,在浏览的过程中也会触发缓存验证。另外,在浏览器偏好设置里设置Advanced->Cache为强制验证缓存也能达到相同的效果。

ETags

Etags是一种缓存的强校验器,相当于缓存的指纹,每个缓存的Etags都不一样,它的原理是:当浏览器向服务器请求某个资源A时,服务器根据资源A计算出一个哈希值并通过Etags响应头发送给客户端,浏览器会把Etags值和资源的内容一同缓存到本地,当下次需要对缓存进行验证时,就会通过If-None-Match: (Etags)的形式发送给服务端,服务端就计算资源A的哈希值与客户端发送的Etags值进行比较,发生变化了就将新的资源A发送给客户端(200),没有变化则返回304。
通过比较Etags值能够快速确定资源是否发生变化,提高效率,客户端也不需要把资源发送给服务端,节省了带宽,etags的唯一性有助于防止资源的同时更新相互覆盖(“空中碰撞”)。

vary头的作用

有时候,同一个 URL 可以提供多份不同的文档,这就要求服务端和客户端之间有一个选择最合适版本的机制,这就是内容协商
协商方式有两种,一种是服务端把文档可用版本列表发给客户端让用户选,这可以使用 300 Multiple Choices 状态码来实现。这种方案有不少问题,首先多一次网络往返,其次服务端同一文档的某些版本可能是为拥有某些技术特征的客户端准备的,而普通用户不一定了解这些细节。举个例子,服务端通常可以将静态资源输出为压缩和未压缩两个版本,压缩版显然是为支持压缩的客户端而准备的,但如果让普通用户选,很可能选择错误的版本。所以 HTTP 的内容协商通常使用另外一种方案:服务端根据客户端发送的请求头中某些字段自动发送最合适的版本。
可以用于这个机制的请求头字段又分两种:内容协商专用字段(Accept 字段)、其他字段
首先来看 Accept 字段,详见下表:

请求头字段说明响应头字段
Accept告知服务器发送何种媒体类型Content-Type
Accept-Language告知服务器发送何种语言Content-Language
Accept-Charset告知服务器发送何种字符集Content-Type
Accept-Encoding告知服务器采用何种压缩方式Content-Encoding

当浏览器向服务器发送的Accept字段中说明了支持的语言、压缩等时,服务器就会根据浏览器给的说明发送响应的数据格式。
有时候,上面四个 Accept 字段并不够用,例如要针对特定浏览器如 IE6 输出不一样的内容,就需要用到请求头中的 User-Agent 字段。类似的,请求头中的 Cookie 也可能被服务端用做输出差异化内容的依据。
由于客户端和服务端之间可能存在一个或多个中间实体(如缓存服务器),而缓存服务最基本的要求是给用户返回正确的文档。如果服务端根据不同 User-Agent 返回不同内容,而缓存服务器把 IE6 用户的响应缓存下来,并返回给使用其他浏览器的用户,肯定会出问题 。
所以 HTTP 协议规定,如果服务端提供的内容取决于 User-Agent 这样「常规 Accept 协商字段之外」的请求头字段,那么响应头中必须包含 Vary 字段,且 Vary 的内容必须包含 User-Agent。
同理,如果服务端同时使用请求头中 User-Agent 和 Cookie 这两个字段来生成内容,那么响应中的 Vary 字段看上去应该是这样的:

Vary: User-Agent, Cookie

也就是说 Vary 字段用于列出一个响应字段列表,告诉缓存服务器遇到同一个 URL 对应着不同版本文档的情况时,如何缓存和筛选合适的版本。

参考文章
链接:
HTTP 缓存
什么是Etag
HTTP 协议中 Vary 的一些研究



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值