浏览器的缓存机制小结

什么是浏览器缓存?

  浏览器缓存(Brower Caching)是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就能够直接从本地磁盘加载文档php

  咱们能够经过 chrome://view-http-cache/ 来查看chrome浏览器缓存了什么内容。 css

  推荐阅读文章:大公司里怎样开发和部署前端代码?html

 

为何要用浏览器缓存?

  • 第一:避免了冗余的数据传输,节省流量。
  • 第二:加快了用户访问网页的速度。
  • 第三:减少了服务器的压力。

  注意,通常,咱们缓存的都是css、js、图片之类的文件,这些文件的改动比较小,而html文件是不缓存的,由于html文件中经常包含动态的内容,好比引入a.css?v=1.0,最后是版本号,若是html也被缓存,那么咱们就没办法达到经过修改版本号进而使得用户获取新内容的目的了。前端

 

 

浏览器缓存有哪些类型?

  缓存类型分为强缓存协商缓存nginx

  强缓存:在用户请求资源时,若是命中强缓存,则不向服务器请求,而直接从本地获取资源。咱们能够看到200状态码,并提示from disk cache或from memory cache(区别后面讲)。 redis

  协商缓存: 在用户请求资源时,浏览器直接则向服务器发送请求,服务器根据 request header 来判断是否命中协商缓存,若是命中,则返回304和新的response header,使用本地资源;不然,返回新的资源。 chrome

  强缓存和协商缓存的共同点:二者命中后都是从本地读取资源。数据库

  强缓存和协商缓存的区别: 强缓存很强势,是没有向服务器发出请求的; 而协商缓存必需要向服务器发一个请求来协商。 apache

 

浏览器缓存有关的header

强缓存

  强缓存是利用http的响应头中的Expires字段和Cache-Control两个字段来控制的,用来表示使用缓存的有效时间。浏览器

Expires

  Expires是http1.0规范的,表示缓存的过时时间。  如某个资源的response heade中的字段: Expires: Fri, 18 Aug 2017 07:57:17 GMT。 表示当浏览器再次加载这个资源时,若是时间没有超过,就命中强缓存,使用内存中缓存的资源。

之因此浏览器在再次加载时能够判断出时间是否超过,是由于浏览器在缓存资源时,不只缓存了资源,还缓存了response header相关的内容,好比这里Expires字段。

缺点:因为不能保证服务器和用户端的绝对时间保持一致,因此缓存有时可能会出现混乱的状况, 在HTTP1.1版本中开始使用Cache-Control的方法进行缓存。

 

 

Cache-Control

  Cache-Control是http1.1规范的,一样表示缓存的过时时间。 其中的max-age是做为判断是否过时的主要判据,它是一个相对时间,单位为s。 如知乎上的某一张图片的response header中的字段:cache-control: public, max-age=31536000。 public表明了这张图片是能够被任何用户缓存的,包括代理服务器等; 而max-age是表示在31536000s(一年)内,若是再次请求就使用本地资源。

  Cache-Control除了max-age的使用以外,还有几个比较重要的字段:

  • no-cache: 不优先使用本地缓存,而是使用协商缓存。注意: 这里并非说必定不适用本地缓存的资源,而是须要先协商一下,若是命中,仍是会使用本地缓存的。
  • no-store:必定不使用本地缓存,每次用户请求资源,都会下载获得服务器发来的最新的资源。
  • public:资源能够被任何用户缓存,包括全部普通用户和代理服务器。
  • private:只能被当前的特定用户缓存,其余用户没法缓存。 通常是说代理服务器不能缓存。 

  

强缓存之Expires、Cache-Control比较

相同点: 二者都是强缓存。

不一样点

  • Expires是http1.0规定的,而Cache-Control是http1.1规定的。
  • Expires的过时时间采用的是绝对时间,容易形成差错; 而Cache-Control的过时时间采用的时相对时间,在缓存上不会出现问题。
  • 二者能够同时存在于一次请求中,可是不会同时在一次请求中起做用。 在HTTP1.0的环境下,Cache-Control不起做用,Expires起做用; 在HTTP1.1的环境之下, Expires不起做用,而Cache-Control起做用。当前通常都是http1.1的状况,因此Expires是做为一种向下兼容的形式而存在的。
  • Cache-Control的选择更多,功能更为强大,推荐使用。 Expires做为强缓存,功能单一,不推荐使用。

 

协商缓存

  协商缓存通常是使用 if-modified-since/last-modified 和 if-none-match/etag 由服务器来决定浏览器缓存的资源是否可使用

 

if-modified-since/last-modified

        在用户请求到资源以后,会返回这个资源,而且在response header中返回一个 last-modifed 字段,这时浏览器就会缓存这个资源以及最后的修改时间, 能够是: last-modified: Fri, 18 Aug 2017 07:27:24 GMT。 接着,当用户再次请求相同的资源时,须要在请求头中添加 if-modified-since 字段,这个字段的值就是以前存储的 last-modifed 的值,服务器获得 if-modified 值以后,会和资源最近的修改时间做比较,若是命中,则返回304,让浏览器使用缓存的资源;不然,返回一个最新的资源而且在 last-modified 修改成最近的资源修改时间。 

 

if-none-match/etag

  在用户请求到资源以后,会返回这个资源,而且在response heade 中返回一个 etag 字段,即 entity tag,这个字段的值是一个字符串,惟一的标识了这个资源,只要资源发生了变化,这个etag值就会发生变化。当用户再次请求资源时,会在request header中携带 if-none-match 字段,其值为上次缓存的 etag 值,若是命中,则返回304,使用缓存资源;不然,服务器返回最新的资源。

 

两种协商缓存机制的比较

相同点: 都是为了协商缓存。 

不一样点

  • 在精度上,Etag优于last-modified。 若是一个文件在1s内改变了不少次,经过etag是能够判断出来并返回最新的资源的,可是last-modifed的精度只能到s,是没法返回最新资源的,准确地说,UNIX记录只能精确到s。 
  • 在准确率上,Etag优于last-modified。有些文件可能总体copy等,只是在时间上发生了变化,而内容上并无发生变化(etag变化,last-modified不变),若是使用last-modified,那么就会返回最新的资源,实际上这是不须要的。
  • 在性能上,last-modified优于Etag。由于last-modified只须要记录时间,而etag须要从新由服务器生成一个hash值,因此在性能上etag略差。
  • 在优先级上,Etag优于last-modified。  也就是说,etag和last-modified是能够同时使用的,可是到服务器端,会优先判断etag,若是相同,直接返回304;若是不一样,就继续比较last-modified,而后再决定是否返回新的资源。

 

 

浏览器缓存过程是怎样的?

  1.  浏览器第一次加载资源,服务器返回200, 浏览器将资源下载下来,把资源和response header相关内容一并缓存。
  2. 下一次加载时,首先比较cache-control,若是没有超过期间,则命中强缓存,不发送请求,直接读取本地文件(若是不支持http1.1,则使用expires来判断);若是时间已通过期,则发送带有if-none-match和if-modified-since的请求头。
  3. 服务器接受到请求以后,首先判断etag是否和服务器上文件的etag一致,若是一致,则命中协商缓存,返回304;若是不一致,返回新的资源并带上新的etag值返回200。
  4. 若是请求中没有etag值,则比较发送来的 if-modified-since 值,若是命中,则返回304,;不然,返回新的资源带上新的last-modified的值并返回状态码200。

 

 

用户行为对浏览器缓存的控制如何? 

  1. 地址栏访问,连接跳转是正经常使用户行为,将会触发浏览器缓存机制
  2. F5刷新,浏览器会设置max-age=0,跳过强缓存判断,进行协商缓存判断
  3. ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源

 

 

实际问题分析

  代码更新到线上后用户浏览器不能自行更新,咱们不能要求客户在系统更新后都进行一次缓存清理的操做。
在资源请求的URL中增长一个参数,好比:js/mian.js?ver=0.7.1。这个参数是一个版本号,每一次部署的时候变动一下,当这个参数变化的时候,强缓存都会失效并从新加载。这样一来,静态资源,部署之后就须要从新加载。这样就比较完美的解决了问题。

 

网站的缓存类型? 

第一级、浏览器缓存

优势: 

这是最省资源的方式,浏览器甚至都不须要发起请求。 

 

缺点:

缓存脱离控制,若是缓存时间太长,用户没法访问最新的页面,特别是出现一个紧急的bug的时候,须要一段时间,才能平息。

 

使用:

在header头部添加Expires、Cache-Control、max-age、last-modified、etag的一个或者是多个,能够在meta中对缓存进行控制。 

 

建议:

js、css、图片能够把缓存时间设置的久一些,永远不过时都是能够的,文件出现变化的时候经过更换(添加)版本号就行更新

 

 

第二级、CDN缓存-静态页面

根据智能DNS解析,用户访问到最近的一台机器,这样就能够减小网络延迟。

用户访问CDN,CDN上若是资源存在而且没有过时,直接返回给用户内容,不然须要先访问源站,而后保存到CDN服务器上面,而后返回用户。

优势

(1)请求分散,削弱了高流量下的压力。

(2)减小了网络延迟。

 

缺点

(1)节点资源可能缓存不一致,致使不一样的用户看到的结果不一样

(2)若是设置过时时间短或者其余的不合理的回源策略(即又访问源服务器),会致使大量回源,致使访问速度变慢。

(3)高并发期间,一个资源,可能会有多个回源请求。

(4)刷新CDN,须要一段时间, 若是出现bug, 也得登上几分钟。

 

 

第三级、proxy缓存-动态页面

  不少代理服务器都支持了缓存,好比Nginx,Apache。一些动态页面或者接口不怎么更新,好比产品列表等,能够把内容缓存到服务器里面,下次请求的时候,直接读取缓存,动态脚本都不须要执行。动态脚本若是要返回的话,可能须要访问数据库,以及一些其余的服务,这就增长了相应时间。

使用:

nginx,能够配置 proxy_cache

apache,能够配置 mod_cache、mod_disk_cache、mod_file_cache以及mod_mem_cache

 

 

第四级、opcode缓存

  是针对php代码。php执行的时候,须要先对php代码解释,生成中间代码,称为opcode,而后再执行。若是缓存住,就能够不须要每一次都解释,这样就能够节省很多资源,增长吞吐量。

优势:

节省资源,增长吞吐量。

 

缺点:

(1)代码更新,须要等待opcode失效,若是设置不过时,那就须要重启服务器。 

(2)opcode主要节省了CPU和内存资源,若是时间消耗主要是磁盘或者是网络IO,那么做用不是太大。

 

 

第五级、文件缓存

  会把计算或者从数据库,以及其余服务得到数据,放到一个文件里面,使用的时候取出来。常见的session就是这么作的。我看phpcms就大量使用这种缓存。
缺点:
1)多台服务器,数据缓存内容可能不一致。为了解决这个问题,曾经挂载共享代理,这就致使磁盘IO成为瓶颈。
2)设置过时时间,不太容易。

 

 

第六级、分布式缓存

为了解决文件缓存存在的问题,就出现了分布式缓存。常见的有memcache,redis.能够搭建集群,设置过时时间。redis,百度都把它当作数据存储来使用。这种缓存在互联网行业当中,大量应用。缺点:须要人维护,消耗大量内存,须要设置过时时间

相关文章
相关标签/搜索