HTTP缓存

Web缓存大致可以分为:数据库缓存、浏览器缓存、服务器缓存(CDN、代理服务器缓存)。

​ 而浏览器缓存也有很多方式,比如:HTTP缓存、localstorage、cookie等,下面将侧重于描述讨论一下HTTP缓存的相关话题。

  • 为什么要使用缓存
  1. 缓存减少了冗余的数据传输,不仅减少了用于流量的费用,还节约了用户的时间(让第二次请求同样的数据加载的更快,页面显示更快)。
  2. 减轻了服务器的负担,有效的缓存可以可以不需要服务器再重新发送,大大提高了网站的性能。
  3. 缓解了网络带宽的问题,不需要更多的带宽就可以更快的加载页面。
  4. 降低了传输时延,因为在信息的传播中,距离越长时延越大,缓存可能存在本地或者较近的(代理)服务器上,不需要更远的距离去请求。

HTTP缓存

http缓存分为 强制缓存协商 / 对比缓存 两种。

Http缓存主要涉及三个角色:一是浏览器,二是浏览器的缓存数据库,三是服务器。

已存在缓存数据时,仅基于强制缓存,请求数据的流程如下:
在这里插入图片描述
已存在缓存数据时,仅基于对比缓存,请求数据的流程如下:
在这里插入图片描述
由上图,我们可以看到两类缓存规则的不同,强制缓存如果生效,不需要再和服务器发生交互,而对比缓存不管是否生效,都需要与服务端发生交互

两类缓存规则可以同时存在,强制缓存优先级高于对比缓存,也就是说,当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存规则。

强制缓存

从上文我们得知,强制缓存,在缓存数据未失效的情况下,可以直接使用缓存数据,那么浏览器是如何判断缓存数据是否失效呢?

我们知道,在没有缓存数据的时候,浏览器向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应header中。

对于强制缓存来说,响应header中会有两个字段来标明失效规则(Expires/Cache-Control)使用chrome的开发者工具,可以很明显的看到对于强制缓存生效时,网络请求的情况。

结合实际的请求来看:
在这里插入图片描述
在打开一个网页时,这些size为from disk cache的即为从磁盘中读取,即命中了强缓存。

  • Expires

Expires的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。

存在的问题是,到期时间是由服务端生成的,是一个绝对时间,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。

Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

HTTP 1.1 的版本,使用Cache-Control替代。

  • Cache-Control

Cache-Control是一个相对时间。由于是相对时间,并且都是与客户端时间比较,所以服务器与客户端时间偏差也不会导致问题。

Cache-Control与Expires可以在服务端配置同时启用或者启用任意一个,同时启用的时候Cache-Control优先级高。

常见的取值有private、public、no-cache、max-age, s-maxage,no-store,默认为private。

  • private :
    表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。

  • public :
    表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。

  • no-cache :
    强制所有缓存了该响应的用户,在使用已缓存的数据前,发送带验证器的请求到服务器。不是字面意思上的不缓存。

  • max-age :
    指定一个时间长度,在这个时间段内缓存是有效的,单位是s。

  • s-maxage :
    同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。

  • no-store :
    不缓存,每次请求都要向服务器重新获取数据。

仅仅是已缓存文件过期了并不意味着它和原始服务器上目前处于活跃状态的文档有实际的区别,只是说到了要审核的时间了,说明缓存需要访问原始服务器是否发生了变化。
如果发生了变化,缓存会获取一份新的文档副本,并且将其存到旧的文档的位置上;如果没有发生变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新。

协商缓存

协商缓存,顾名思义,需要进行比较判断是否可以使用缓存。

浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。
再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。

缓存标识在请求header和响应header间进行传递,一共分为两种标识传递。

Last-Modified / If-Modified-Since
  • Last-Modified:
    浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

  • If-Modified-Since:
    当浏览器再次请求该资源时,发送的请求头中会包含If-Modify-Since,该值为缓存之前返回的Last-Modify。
    服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。
    若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;如果命中缓存,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache,并且不会返回资源内容。

Etag / If-None-Match

但是有时候通过最后修改时间来判断资源是否修改还是不太准确(资源变化了最后修改时间也可以一致)。于是出现了ETag/If-None-Match。他的优先级高于Last-Modified / If-Modified-Since。

与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化。

ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。

第一次客户端访问资源的时候,服务端返回资源内容的同时返回了ETag : XXXX。

第二次客户端访问资源的时候,由于缓存中已经有了Etag为 XXXX的资源,带上了If-None-Match : XXXX。告诉服务端:如果你那边的资源还是XXXX标签的资源,你就返回304告诉我,不需要返回资源内容了;如果不是的话,你再返回资源内容给我就行了。服务端就比较下Etag来看是返回304还是200。

既生Last-Modified何生Etag?

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  1. Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间

  2. 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存

  3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。

例子:结合具体的请求来看,首先是第一次发送某请求后服务器的response:
在这里插入图片描述
两个字段etag和last-modified是用于协商缓存的规则字段。其中etag是所请求的数据在服务器中的唯一标识,而last-modifind标识所请求资源最后一次修改的时间。

在缓存时间3600秒过去之后,我们再次发起同样的请求:
在这里插入图片描述
可以看到,在我们的请求中有这样两个字段if-modifind-since和if-none-match,两个字段分别对应着响应中的last-Modified和etag,用来对协商缓存进行判断:

  1. 首先,如果在第一次请求中有etag和last-modified时,缓存数据库会保存这两个字段,并且在再次发起同样的请求时以if-none-match和if-modified-since发送保存的last-modified和etag数据。
  2. 服务器收到请求后会以优先级if-none-match > if-modifind-since的顺序进行判断,如果资源的etag和if-none-match相等,即所请求的资源没有变化,此时浏览器即可以使用缓存数据库中的数据,此时http的请求状态码为304,请求的资源未变化。
  3. 如果请求字段中没有if-none-match,就使用if-modified-since来判断。如果if-modified-since的值和所请求的资源时间一致,即所请求的资源相同,浏览器即可以使用缓存数据库中的数据。http状态码304。

最后以流程图的形式总结浏览器缓存机制:
在这里插入图片描述

各种刷新

理解了上面的缓存标签之后就很好理解各种刷新了。

刷新有三种

浏览器中写URL,回车
F5
Ctrl+F5

假设对一个资源:

浏览器第一次访问,获取资源内容和cache-control: max-age:600,Last_Modify: Wed, 10 Aug 2013 15:32:18 GMT于是浏览器把资源文件放到缓存中,并且决定下次使用的时候直接去缓存中取了。

  • 浏览器url回车

    浏览器发现缓存中有这个文件了,好了,就不发送任何请求了,直接去缓存中获取展现。(最快)

  • 下面我按下了F5刷新

    F5就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器就胆胆襟襟的发送一个请求带上If-Modify-since:Wed, 10 Aug 2013 15:32:18 GMT

    然后服务器发现:诶,这个文件我在这个时间后还没修改过,不需要给你任何信息了,返回304就行了。于是浏览器获取到304后就去缓存中欢欢喜喜获取资源了。

  • 下面我们按下了Ctrl+F5

    这个可是要命了,告诉浏览器,你先把你缓存中的这个文件给我删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作…

用户行为与缓存:
在这里插入图片描述

参考文章:https://juejin.im/entry/599afbe5f265da247c4ee6e3https://blog.youkuaiyun.com/Jutal_ljt/article/details/80021545

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值