louzhedong/blog

浏览器缓存详解

louzhedong opened this issue · 0 comments

浏览器缓存

缓存贯穿于浏览器访问的方方面面,深入理解缓存能带给我们的程序更高效的性能

但缓存使用不当也会对我们的开发造成困惑

缓存的类型
  1. 强缓存

    用户发送的请求,直接从客户端缓存中获取,不与服务器发生交互

  2. 协商缓存

    用户发送的请求,需要到达服务器,由服务器判断是否从缓存中获取资源

  3. 注意点:

    客户端最后获取到的数据最后都是从客户端缓存中获取的,在协商缓存中由服务端判断是否使用客户端中的缓存

强缓存

强缓存包括 expires 和 cache-control

expires是http1.0的内容,在高级的浏览器中会被cache-control覆盖掉

expires中保存的是服务器的过期时间,当客户端和服务器时间不一致时,缓存会出现偏差

cache-control的类型:

  • public:所有内容都将被缓存(客户端和代理服务器都可缓存)

  • private:所有内容只有客户端可以缓存,Cache-Control的默认取值

  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定

  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存

  • max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效

  • s-maxage:只用于共享缓存,比如CND缓存。如果存在s-maxage,则会覆盖max-age和expires

cache-control的判断流程可以查看下图:

协商缓存

协商缓存分类

  • If-Modified-Since 和 Last-Modified
  • If-None-Match 和 Etag

其中后者会覆盖前者,它们各自的含义:

  • Last-modified: 表明请求的资源上次的修改时间。

  • If-Modified-Since:客户端保留的资源上次的修改时间。

  • Etag:资源的内容标识。(不唯一,通常为文件的md5或者一段hash值,只要保证写入和验证时的方法一致即可)

  • If-None-Match: 客户端保留的资源内容标识。

    1) 分布式系统尽量关闭Etag,因为每台机器生成的Etag都不一样。
    2)分布式系统里多台机器间文件的Last-Modified必须一致,以免负载均衡不同导致对比失败。

Last-Modified的问题:

  1. 文件的内容并没有发生改变(我删除了一个字母,然后又加上,重新保存),这样也会导致文件修改时间改变。
  2. 文件修改时间的单位是精度是秒,而当修改过于频繁,在秒一下单位修改,那么就会导致文件已经修改但是修改时间没有变
  3. 每个CDN保存文件的修改时间可能不一样
缓存的来源
  1. from disk cache

    从磁盘中获取缓存资源,等待下次访问时不需要重新下载资源,而直接从磁盘中获取。它的直接操作对象为CurlCacheManager。

  2. from memory cache

    从内存中获取资源,等待下次访问时不需要重新下载资源,而直接从内存中获取。Webkit早已支持memoryCache。
    目前Webkit资源分成两类,一类是主资源,比如HTML页面,或者下载项,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接,分别对应代码中两个类: MainResourceLoader和SubresourceLoader。虽然Webkit支持memoryCache,但是也只是针对派生资源,它对应的类为CachedResource,用于保存原始数据(比如CSS,JS等),以及解码过的图片数据。

  3. 比较

    当退出进程时,内存中的数据会被清空,而磁盘的数据不会,所以,当下次再进入该进程时,该进程仍可以从diskCache中获得数据,而memoryCache则不行。

浏览器缓存行为