浅析浏览器缓存机制

浏览器缓存机制

浏览器缓存机制,其实主要就是 HTTP协议定义的缓存机制
但是也有非 HTTP 协议定义的缓存机制,例如:HTML中的 mata 标签定义的缓存:<meta http-equive='Pragma' content='no-catche'> 这个代码告诉浏览器上述页面不缓存,这样页面每次访问都会从新去服务器拉取。使用很简单,但是只有(IE)支持,并且代理服务器不支持这种缓存,因为代理服务器不会读取解析 HTML 内容本身。这个仅对页面有效,对页面的资源无效。 <meta http-equive='expires' content='mon, 18 apr 2016 14:30:00 GMT'> 也是仅有IE支持。 优先级: Pragma > Cache-Control > Expires

  • 浏览器缓存是如何工作的?
    浏览器发出的所有 HTTP 请求会首先被路由到浏览器的缓存,以查看是否缓存了可以用于实现请求的有效响应。核心就是浏览器把请求过来的结果保存在了本地、或者内存中。而不用每次都想服务器发送相同的请求。如果多次打开相同的页面,第一次访问这个页面的时候,浏览器将下载下来的js、css、图片 保存在了本地,之后的每次请求,这些需要下载的js、css、图片 都从本地读取,那么效率就快了很多。但是如果每次都从浏览器读取缓存,如果数据、文件发生了变化,那么不就展示了错误的、过时的信息了嘛。因此:
    1. 强缓存:服务端和浏览器约定一个有效期,请求发起之前,判断:如果有效期过了,那么就不走缓存,从新从服务器请求新的数据,如果还在有效期之内,那么就走缓存,不请求接口了。
    2. 协商缓存:浏览器向服务器发起一个新的请求,有可能存在这个请求已经超出了有效期,但是这个文件并没有发生变更,其实还是可以使用缓存数据的。如何判断文件是否有更新呢?两张方式:
      1. 在上一次服务端告诉客户端约定的有效期的同时,同时响应头中(Response-Headers)告诉服务端这个文件的最后更新时间(Last-Modified)。当重新请求试图再次下载这个文件的时候,请求头(Request-Headers)中带上这个最后更新时间(If-Modified-Since),服务器检查这个更新时间和服务端这个文件的最后更新时间是否一致,不一致,则更新,重新请求,下载正确的数据,相应头中返回 Last-Modified, 更新Last-Modified;如果一致表示没有更新,返回304,客户端可以使用读取缓存。
      2. 在上一次服务端告诉客户端约定的有效期的同时,同时响应头中(Response-Headers)告诉服务端这个文件的版本号 (ETag),当服务端更新该文件的时候,重新生成一个独一无二的版本号。再次发送请求的时候,请求头(Request-Headers) 中带上这个文件的版本号(If-None-Match: '212143565764343') check 一下版本号是否一致,如果一致,接口返回304,读取缓存就行了,如果不一致,下载正确的数据,同时相应头中返回 ETag,跟新本地这个文件的 ETag

强缓存

  • Expires: Wed, 29 July 2021 08:43:55 GMT。 表示缓存到期时间。
    Expires 的值是一个时间点,表示这个缓存的到期时间。这是HTTP 1.0 的产物。时间(UTC)是由服务器发送的可能存在误差,如果客户端与服务器时间存在差异,可能会出现问题。存在版本问题,如果文件到期之前修改了,客户端不可知。

  • Cache-Control: public, max-age=2552; 这是HTTP 1.1 的产物。存在版本问题,如果文件到期之前修改了,客户端不可知。。Cache-Control的参数可以设置很多值,也可以组合使用,逗号隔开。譬如

### 在请求中使用Cache-Control 时,它可选的值有:
 - no-cache  告知代理服务器不直接使用缓存,要向源服务器发起请求。
 - no-store   用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不会被缓存到内存或者 internet 临时文件中。**优先级最高**
 - max-age=2552   告知服务器客户端希望获取一个在小于 2552 s 内更新过的资源。
 - max-stale[=delta-seconds] 告知(代理)服务器客户端愿意使用一个超出缓存时间的资源。如果有值,那么超出缓存时间为 delta-seconds ,没有,则为任意超出时间。
 - min-fresh   指示客户机可以接收超出 响应时间小于当前时间加上指定时间的响应。
 - no-transform  告知(代理)服务器客户端希望获取一个没有被转换过(比如:压缩)的资源。
 - only-if-cached 告知(代理)服务器客户端希望获取一个缓存内容(如果有的话),而不用向源服务器请求。
 - cache-extension  自定义扩展值,如果服务器不识别,则忽略。
### 在响应中使用Cache-Control 时,它可选的值有:
 - public   任何情况下该资源都将被缓存。(即使是需要HTTP认证的资源)
 - Private[='filed-name']   指示对于返回报文整个或部分响应(若指定了 filed-name 则为 filed-name的字段数据)仅开放给部分用户(服务器指定的 share-name 如代理服务器)做缓存使用,不能被共享缓存处理。这个相应消息对于其他用户的请求无效。服务端不用缓存,只有客户端使用缓存。(cache-control 的默认取值)
 - max-age=2552   告知客户端该资源在 2552s 内是新鲜的,而不用想服务端发起请求。
 - s-max-age=delta-seconds 同max-age,但仅应用于 共享缓存(如代理)。
 - no-cache  指示请求或者响应消息不直接使用缓存,但是是否使用缓存需要经过协商缓存来验证决定。
 - no-store  所有的内容都不会被保存到缓存或者 internet 临时文件中。
 - only-if-cached 告知(代理)服务器客户端希望获取一个缓存内容(如果有的话),而不用向源服务器请求、
 - must-revalidate  当前资源一定是向源服务发起请求验证的,而不是代理服务器上的缓存。若请求失败,则会返回504。
 - proxt-revalidate  和must-revalidate 一样,但是仅能应用于共享缓存(代理服务器)。
 - cache-extension 自定义扩展值,如果服务器不识别则忽略。

**如果Expire 和 Cache-Control中的max-age 同时存在,那么优先考虑max-age。**

协商缓存:要配合Cache-Control使用。

  • Last-Modified / If-Modified-Since | If-Umnmodified-Since(最后更新时间是否不一致)

  • ETag / If-None-Match | If-Match(ETag是否一致) 实际上ETag并不是文件的版本号,而是一串可以代表该文件唯一的字符串。

**如果ETag 和 Last-Modified 同时存在,那么优先考虑ETag。**

HTTP 1.1 出现的 ETag的出现主要是为了解决几个 Last-Modified的难以解决的问题:
  1. Last-Modified 的最小单位精确到 秒,如果文件在一秒钟之内改变了多次,那么它将不能准确标注文件的修改时间
  2. 如果某一个文件是注定会被定期生成的,即使它的内容没有发生改变,那么它的 Last-Modified 也会发生改变,导致没法使用缓存
  3. 有可能存在服务器没有准确获取文件修改时间的问题,也或者与代理服务器时间不一致的情形。
ETag 也不是完美无缺的:
  1. 计算ETag 需要性能损耗。
  2. 如果是分布式服务器存储的时候,计算ETag的算法不一致,会导致ETag不一致。从一台服务器上请求过来的资源去另外一台服务器上进行文件校验的时候ETag不一致。

不能使用缓存的情况:

  1. post 请求 无法被缓存
  2. HTTP信息头中包含:Cache-Control: no-cache; Pragma: no-cache(HTTP 1.0) 或者 Cache-Control: max-age=0;等告诉浏览器不用缓存。
  3. HTTP 响应头中不包含:Etag\Last-Modified 也不包含:Expires\Cache-Control 的请求无法被缓存。
  4. 需要根据 Cookie,认证信息等决定输入内容的动态请求是不能被缓存的。
  5. 经过 HTTPS 安全加密的请求。(也有人经过测试发现,IE其实在头部加上Cache-Control: max-age信息,Firefox在 Cache-Control: public之后能够对HTTPS的资源进行缓存,参考《HTTPS的七个误解》http://www.ruanyifeng.com/blog/2011/02/seven_myths_about_https.html

用户行为与浏览器缓存

1. 地址栏回车               强缓存(Expires/Cache-Control):有效          协商缓存(Last-Modified/ETag):有效
2. 页面链接跳转             强缓存(Expires/Cache-Control):有效          协商缓存(Last-Modified/ETag):有效
3. 新开窗口                强缓存(Expires/Cache-Control):有效          协商缓存(Last-Modified/ETag):有效
4. 浏览器的前进、后退        强缓存(Expires/Cache-Control):有效          协商缓存(Last-Modified/ETag):有效
5. F5 刷新                 强缓存(Expires/Cache-Control):失效          协商缓存(Last-Modified/ETag):有效
6. ctrl + F5 强制刷新       强缓存(Expires/Cache-Control):失效           协商缓存(Last-Modified/ETag):失效

废弃和更新已缓存的策略:

如果资源已经被修改,但是这个资源被缓存了,客户端因为 Expires \ max-age 无法看到最新的修改。如何解决? 无法解决,这是一个伪命题,我们只能通过改变资源文件的请求网址。  给资源文件名加上 指纹码(或者版本号)

定义缓存策略的方法和技巧:

1. **使用一致的网址**:如果在不同的网址中提供相同的内容,将会多次获取和存储该内容。(网址区分大小写)
2. **确保服务器提供验证令牌ETag**。通过验证令牌,如果服务器上的资源未被更改,就不必传输相同的字节。
3. **确定中继缓存可以缓存哪些资源**。对所有用户完全相同的请求资源很适合由CDN或其他中继缓存进行缓存。
4. **确定每个资源的最有缓存周期**。不同的资源可能有不同的更新要求,审查并确定每个资源的max-age。
5. **确定网站的最佳缓存层级**。对HTML文档使用组合使用包含指纹码的资源网址,短时间、no-cache的生命周期,可以控制客户端获取更新的速度。
6. **搅动最小化**。有些资源的更新可能会比其他资源更新更频繁。如果资源的饿特定部分(例如:javascript 函数、css样式)会经常更新,应该考虑将其代码作为单独的文件提供。这样每次获取更新时,剩余内容(不会频繁更新的代码)可以中缓存中获取,确保下载的内容量最少。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容