http协商缓存VS强缓存

以前一直对浏览器缓存只能描述一个大概,深层次的原理不能描述上来;终于在前端的两次面试过程当中被问倒下,为了泄恨,查阅一些资料最终对其有了一个更深刻的理解,废话很少说,赶忙来看看浏览器缓存的那些事吧,有不对的地方,请各位不吝赐教啊。html

 本文主要讲解浏览器端的缓存,缓存的做用是不言而喻的,可以极大的改善网页性能,提升用户体验。前端

一、浏览器缓存

缓存这东西,第一次必须获取到资源后,而后根据返回的信息来告诉如何缓存资源,可能采用的是强缓存,也可能告诉客户端浏览器是协商缓存,这都须要根据响应的header内容来决定的。下面用两幅图来描述浏览器的缓存是怎么玩的,让你们有个大概的认知。面试

浏览器第一次请求时:浏览器

浏览器后续在进行请求时:缓存

 

 从上图能够知道,浏览器缓存包含两种类型,即强缓存(也叫本地缓存)和协商缓存,浏览器在第一次请求发生后,再次请求时:服务器

  • 浏览器在请求某一资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息,包括缓存header信息;本次请求根本就不会与服务器进行通讯;在firebug下能够查看某个具备强缓存资源返回的信息,例如本地firebug查看的一个强缓存js文件



  • 若是没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,可是并不返回资源内容,它会告知浏览器能够直接从缓存获取;不然返回最新的资源内容

强缓存与协商缓存的区别,能够用下表来进行描述:post

  获取资源形式 状态码 发送请求到服务器
强缓存  从缓存取  200(from cache) 否,直接从缓存取
协商缓存  从缓存取  304(not modified) 是,正如其名,经过服务器来告知缓存是否可用

 

二、强缓存相关的header字段

强缓存上面已经介绍了,直接从缓存中获取资源而不通过服务器;与强缓存相关的header字段有两个:性能

  1. expires,这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如Mon, 10 Jun 2015 21:31:12 GMT,若是发送请求的时间在expires以前,那么本地缓存始终有效,不然就会发送请求到服务器来获取资源

  2. cache-control:max-age=number,这是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对值;资源第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过时时间,再拿这个过时时间跟当前的请求时间比较,若是请求时间在过时时间以前,就能命中缓存,不然就不行;cache-control除了该字段外,还有下面几个比较经常使用的设置值:

    • no-cache:不使用本地缓存。须要使用缓存协商,先与服务器确认返回的响应是否被更改,若是以前的响应中存在ETag,那么请求的时候会与服务端验证,若是资源未被更改,则能够避免从新下载。

    • no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。

    • public:能够被全部的用户缓存,包括终端用户和CDN等中间代理服务器。

    • private:只能被终端用户的浏览器缓存,不容许CDN等中继缓存服务器对其缓存。

  注意:若是cache-control与expires同时存在的话,cache-control的优先级高于expiresspa

三、协商缓存相关的header字段

协商缓存都是由服务器来肯定缓存资源是否可用的,因此客户端与服务器端要经过某种标识来进行通讯,从而让服务器判断请求资源是否能够缓存访问,这主要涉及到下面两组header字段,这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段(Last-Modified或者Etag),则后续请求则会带上对应的请求字段(If-Modified-Since或者If-None-Match),若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段代理

  1. Last-Modified/If-Modified-Since
    两者的值都是GMT格式的时间字符串,具体过程:
      • 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间

      • 浏览器再次跟服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值

      • 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,若是没有变化则返回304 Not Modified,可是不会返回资源内容;若是有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,由于既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header

      • 浏览器收到304的响应后,就会从缓存中加载资源

      • 若是协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modified的Header在从新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值

  2. Etag/If-None-Match
    这两个值是由服务器生成的每一个资源的惟一标识字符串,只要资源有变化就这个值就会改变;其判断过程与Last-Modified/If-Modified-Since相似,与Last-Modified不同的是,当服务器返回304 Not Modified的响应时,因为ETag从新生成过,response header中还会把这个ETag返回,即便这个ETag跟以前的没有变化。

 四、既生Last-Modified何生Etag

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

  • 一些文件也许会周期性的更改,可是他的内容并不改变(仅仅改变的修改时间),这个时候咱们并不但愿客户端认为这个文件被修改了,而从新GET;

  • 某些文件修改很是频繁,好比在秒如下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改没法判断(或者说UNIX记录MTIME只能精确到秒);

  • 某些服务器不能精确的获得文件的最后修改时间。

这时,利用Etag可以更加准确的控制缓存,由于Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的惟一标识符。

Last-Modified与ETag是能够一块儿使用的,服务器会优先验证ETag,一致的状况下,才会继续比对Last-Modified,最后才决定是否返回304

五、用户的行为对缓存的影响

盗用网上的一张图,基本能描述用户行为对缓存的影响

 

 

出处:http://www.cnblogs.com/wonyun/p/5524617.html

相关文章
相关标签/搜索