Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >web性能优化之:no-cache与must-revalidate深入探究

web性能优化之:no-cache与must-revalidate深入探究

作者头像
IMWeb前端团队
发布于 2017-12-29 07:00:36
发布于 2017-12-29 07:00:36
1.7K00
代码可运行
举报
文章被收录于专栏:IMWeb前端团队IMWeb前端团队
运行总次数:0
代码可运行

引言

稍微了解HTTP协议的前端同学,相比对Cache-Control不会感到陌生,性能优化时经常都会跟它打交道。

常见的值有有privatepublicno-storeno-cachemust-revalidatemax-age等。

各个取值所代表的含义,网上总结挺多的,这里就不打算再进行逐一介绍,感兴趣的可以一起探讨交流。

本文仅挑no-cachemust-revalidate 这两个进行值进行探究对比。在项目实践中,这两个值用的比较多,也比较容易搞混。

Cache-Control: no-cache Cache-Control: max-age=60, must-revalidate

传送门:RFC2616关于Cache-Control首部的介绍。 如果对论证过程不感兴趣,也可以直接跳到“对比结论”小节查看结论。

no-cache、must-revalidate简介

  • no-cache: 告诉浏览器、缓存服务器,不管本地副本是否过期,使用资源副本前,一定要到源服务器进行副本有效性校验。
  • must-revalidate:告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。

上面的介绍涉及三个主体:浏览器缓存服务器源服务器。下面小节会简单进行介绍。

浏览器、缓存服务器、源服务器

  • 浏览器:资源请求直接发起方。
  • 源服务器:资源实际提供方。
  • 缓存服务器:在浏览器、源服务器之间架设的中间服务器,由它代替浏览器,向源服务器发起资源请求;

缓存服务器作用如下。缓存服务器不是必须的,浏览器可也可与源服务器直接通信。

加速资源访问速度,降低源服务器的负载。缓存服务器从源服务器获取资源,并返回给浏览器。此外,缓存服务器一般还会在本地保存资源的副本,当有相同的资源请求到来,缓存服务器可返回资源副本,以此提高资源访问速度。

对比测试场景、环境准备

对比测试场景

下文会通过以下两种场景的对比测试,来探究no-cachemust-revalidate的区别。

  1. 浏览器 直接访问 源服务器。
  2. 浏览器 通过 缓存服务器,间接访问 源服务器。

环境准备

  • 操作系统:OSX 10.11.4
  • 浏览器:Chrome 52.0.2743.116 (64-bit)、Firefox 49.0.2
  • 缓存服务器:Squid 3.6
  • 源服务器:Express 4.14.0

1、下载实验代码:可以访问github主页获取,也可通过git clone下载到本地。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git clone https://github.com/chyingp/tech-experiment.git
cd tech-experiment/2016.10.25-cache-control/
npm install

2、安装Squid,步骤略,下载地址

3、可选:启动Squid,并将本地http代理设置为Squid的ip和端口。

备注:测试场景“通过缓存服务器,间接访问源服务器资源”时,才需要这一步。

4、可选:将本地代理设置为Charles的地址,然后将Charles的代理地址设置为squid的代理地址。(避免浏览器开发者工具对request header的修改,干扰实验结果)

场景一:浏览器->源服务器

首先,通过以下脚本启动本地服务器(源服务器)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd connect-directly 
node server.js

Cache-Control: no-cache

用例1:二次访问,源服务器 上 资源 未发生变化

访问地址为:http://127.0.0.1:3000/no-cache

步骤一:第一次访问,返回内容如下。可以看到,返回了Cache-Control: no-cache

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-s0vwqaICscfrawwztfPIiA"
Date: Wed, 26 Oct 2016 07:46:28 GMT
Connection: keep-alive

步骤二:第二次访问,返回内容如下。返回状态码为304 Not Modified,表示经过校验,源服务器上的资源没有变化,浏览器可以采用本地副本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 304 Not Modified
X-Powered-By: Express
Cache-Control: no-cache
ETag: W/"b-s0vwqaICscfrawwztfPIiA"
Date: Wed, 26 Oct 2016 07:47:31 GMT
Connection: keep-alive

用例2:二次访问,源服务器 上 资源 发生变化

步骤一:访问地址为:http://127.0.0.1:3000/no-cache?change=1 备注:change=1告诉源服务器,每次访问都返回不同内容

步骤一:第一次访问,内容如下,不赘述。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-8n8r0vUN+mIIQCegzmqpuQ"
Date: Wed, 26 Oct 2016 07:48:01 GMT
Connection: keep-alive

步骤二:第二次访问,返回内容如下。注意Etag变化了,表示源服务器资源已发生变化。于是状态码为200 OK,源服务器返回新版本的资源给浏览器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-0DK7Mx61dfZc1vIPJDSNSQ"
Date: Wed, 26 Oct 2016 07:48:38 GMT
Connection: keep-alive

Cache-Control: must-revalidate

访问地址:http://127.0.0.1:3000/must-revalidate 可选参数说明:

  • max-age:源站返回的内容,max-age是多少(单位是s)。
  • change:源站返回的内容,是否变化,如果是1,则变化。

用例1:二次访问,浏览器缓存未过期

访问地址:http://127.0.0.1:3000/must-revalidate?max-age=10 备注:max-age=10表示,希望资源缓存10s

步骤一:第一次访问,返回内容如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: max-age=10, must-revalidate
Content-Type: text/html; charset=utf-8
Content-Length: 16
ETag: W/"10-dK948plT5cojN3y7Cy717w"
Date: Wed, 26 Oct 2016 08:06:16 GMT
Connection: keep-alive

步骤二:第二次访问(在10s内),如下截图所示,浏览器直接从本地缓存里读取资源副本,并没有重新发起HTTP请求。

用例2:二次访问,浏览器缓存已过期,源服务器 资源未变化

步骤一:第一次访问略过。第二次访问如下截图所示(10s后),返回304 Not Modified

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HTTP/1.1 304 Not Modified
X-Powered-By: Express
Cache-Control: max-age=10, must-revalidate
ETag: W/"10-dK948plT5cojN3y7Cy717w"
Date: Wed, 26 Oct 2016 08:09:22 GMT
Connection: keep-alive

用例3:浏览器缓存已过期,源服务器 资源 已变化

访问地址:http://127.0.0.1:3000/must-revalidate?max-age=10&change=1

步骤一:第一次访问,截图如下。

步骤二:第二次访问(10s后),返回截图如下,可以看到返回了200

场景2:浏览器->缓存服务器->源服务器

从上面的对比实验已经知道,在不经过缓存服务器的情况下,no-cachemust-revalidate在缓存校验方面的差别。

接下来,我们再看下,引入缓存服务器后,二者表现的差异点。

备注:下文我们会通过查看Squid的访问日志,来确认缓存服务器的行为。这里对日志中的几个关键字先粗略解释下:

  • TCP_MISS:没有命中缓存。有可能是缓存服务器不存在资源的副本,也有可能资源副本已过期。
  • TCP_MEM_HIT:命中了缓存。缓存服务器存在资源的副本,并且副本未过期。

再次贴上之前的图。

Cache-Control: no-cache

用例1:chrome第一次访问资源

chrome访问截图如下:200 ok

squid日志:TCP_MISS,表示没有命中本地资源副本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477501799.573     17 127.0.0.1 TCP_MISS/200 299 GET http://127.0.0.1:3000/no-cache - HIER_DIRECT/127.0.0.1 text/html

用例2:chrome再次访问该资源。且源服务器上,该资源未变化

访问地址:http://127.0.0.1:3000/no-cache

第一次访问略。第二次访问,chrome访问截图如下:

squid访问日志如下:TCP_MISS/304 。表示缓存服务器 联系了 源服务器,发现内容没变化,于是返回304。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477501987.785      1 127.0.0.1 TCP_MISS/304 238 GET http://127.0.0.1:3000/no-cache - HIER_DIRECT/127.0.0.1 -

用例3:chrome再次访问该资源。且源服务器上,该资源已变化

访问地址:http://127.0.0.1:3000/no-cache?change=1 备注:change=1 表示强制每次访问源服务器,返回的资源都是新的。

第一次访问略。第二次访问,chrome截图如下,状态码为200

从squid日志来看,缓存服务器 访问 源服务器,并返回200给浏览器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477647837.216      1 127.0.0.1 TCP_MISS/200 299 GET http://127.0.0.1:3000/no-cache? - HIER_DIRECT/127.0.0.1 text/html

Cache-Control: must-revalidate

用例1:缓存服务器 已存在 资源副本,且该资源副本 未过期

访问地址:http://127.0.0.1:3000/must-revalidate?max-age=900 备注:max-age=900表示资源有效期是900s

步骤一:

chrome第一次访问 该资源,缓存服务器上没有该资源副本,于是访问源服务器。最终,缓存服务器给浏览器返回200。此时,缓存服务器squid上有了资源的副本。

步骤二:

firefox第一次访问 该资源(900s内)。缓存服务器上已有该资源副本,且该副本未过期。于是,缓存服务器给firefox返回该资源副本,且状态码为200。(缓存命中)

为了验证步骤二中,缓存服务器 返回的是本地资源的副本,查看squid日志。其中,第二条就是firefox的访问记录,TCP_MEM_HIT/200表示命中本地缓存。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477648947.594      5 127.0.0.1 TCP_MISS/200 325 GET http://127.0.0.1:3000/must-revalidate? - HIER_DIRECT/127.0.0.1 text/html
1477649012.625      0 127.0.0.1 TCP_MEM_HIT/200 333 GET http://127.0.0.1:3000/must-revalidate? - HIER_NONE/- text/html

用例2:缓存服务器 已存在 资源副本,该资源副本已过期,但源服务器上 资源未改变

访问链接:http://127.0.0.1:3000/must-revalidate?max-age=10

用chrome先后访问该资源,其间间隔超过10s。第二次访问时,chrome收到响应如下。

查看squid日志。可以看到,状态为TCP_MISS/304,表示本地副本已过期,跟源服务器进行校验,发现源服务器上资源未改变。于是,给浏览器返回304。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477649429.105     11 127.0.0.1 TCP_MISS/304 258 GET http://127.0.0.1:3000/must-revalidate? - HIER_DIRECT/127.0.0.1 -

用例3:缓存服务器 已存在 资源副本,该资源副本 已过期,但源服务器上 资源已改变

访问地址:http://127.0.0.1:3000/must-revalidate?max-age=10&change=1

用chrome先后访问该资源,其间间隔超过10s。第二次访问时,chrome收到响应如下

squid日志如下,状态都是TCP_MISS/200,表示没有命中缓存。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1477650702.807      8 127.0.0.1 TCP_MISS/200 325 GET http://127.0.0.1:3000/must-revalidate? - HIER_DIRECT/127.0.0.1 text/html

1477651020.516      4 127.0.0.1 TCP_MISS/200 325 GET http://127.0.0.1:3000/must-revalidate? - HIER_DIRECT/127.0.0.1 text/html

对比结论

以下针对的都是浏览器第n次访问资源。(n>1)

不考虑缓存服务器

首部

本地缓存是否过期

源服务器资源是否改变

是否重新校验

状态码

no-cache

不确定

304

no-cache

不确定

200

must-revalidate

是/否

200(来自浏览器缓存)

must-revalidate

304

must-revalidate

200

考虑缓存服务器

首部

本地缓存是否过期

缓存服务器副本是否过期

源服务器资源是否改变

是否重新校验

状态码

no-cache

不确定

不确定

304

no-cache

不确定

不确定

200

must-revalidate

是/否

是/否

200(来自浏览器缓存)

must-revalidate

是/否

304(来自缓存服务器)

must-revalidate

304

must-revalidate

200

写在后面

经过一轮对比测试,发现no-cachemust-revalidate这两个值还是蛮有意思的。实际上,由于篇幅原因,这里还有一些内容尚未进行对比实验。比如:

  • must-revalidateno-cachemax-stale一起使用时的表现。
  • no-cachemax-age=0, mustvalidate的区别。
  • no-chche制定具体的字段名时,跟不指明具体字段名时,缓存校验行为上的区别。
  • proxy-revalidatemust-revalidate的区别。
  • 缓存服务器本身优化算法对实验结果的影响。

对比实验过程比较枯燥繁琐,如有不严谨或错漏的地方,敬请指出 :)

这里留个经常会碰到的问题,供读者探讨:no-cachemax-age=0, mustvalidate的区别。

相关链接

RFC2616 14.9: Cache-Control https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Web 开发人员需知的 Web 缓存知识
今天踩着前辈们的肩膀,再次把这篇文章翻译整理下。一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~~
后端技术探索
2018/08/09
5690
Web 前端性能优化准则
“只有10%-20%的最终用户响应时间花在接收请求的HTML文档上,剩下的80%-90%时间花在HTML文档所引用的所有组件(图片,script,css,flash等等)进行的HTTP请求上”
书童小二
2018/09/03
1.1K0
Web 前端性能优化准则
设计一个完美的HTTP缓存策略
作为一个前端,了解http缓存是非常必要,它不仅是面试的必要环节,也更是实战开发中必不可少需要了解的知识点,本文作者将从缓存的概念讲到如何在业务中设计一个合理的缓存架构,带你一步一步解开http缓存的神秘面纱。
星哥玩云
2022/07/28
6190
设计一个完美的HTTP缓存策略
Nginx下关于缓存控制字段cache-control的配置说明 - 运维小结
HTTP协议的Cache -Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置 Cache-Control并不会影响另一个消息处理过程中的缓存处理过程。 请求时的缓存指令包括: no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached等。 响应消息中的指令包括: public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。
洗尽了浮华
2019/05/25
9.2K0
一篇文章带你详解 HTTP 协议之报文首部及字段详解(中)
先来回顾一下首部字段在报文的位置,HTTP 报文包含报文首部和报文主体,报文首部包含请求行(或状态行)和首部字段。 在报文众多的字段当中,HTTP 首部字段包含的信息最为丰富。首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息等内容。
java进阶架构师
2018/08/15
2.1K0
一篇文章带你详解 HTTP 协议之报文首部及字段详解(中)
HTTP各种特性总览
将其中的*设置为某个域名,那么则标识只允许某个域名可以访问。但是只能一个域名,如果需要多个域名需要增加服务器逻辑进行判断。
Dreamy.TZK
2020/08/14
2970
Web缓存 - HTTP协议缓存
Web缓存一般分为浏览器缓存、代理服务器缓存以及网关缓存,本文主要讲的是 浏览器缓存,其它两种缓存大家自行去了解下。
laixiangran
2018/07/25
1K0
Web缓存 - HTTP协议缓存
[日常] HTTP的缓存
web缓存: 1.可以自动保存常见文档副本的HTTP设备,当web请求抵达缓存时,如果存在缓存副本,就直接从本地存储设备返回,而不是去源服务器获取 2.缓存命中和未命中 3.HTTP再验证,检测服务器上的内容是否发生了变化,新鲜度检测规则。缓存对副本进行再验证时,会向服务器发送一个小的再验证请求,如果没变化,服务器会返回304 Not Modified,get请求中添加if-modified-since会进行再验证 4.缓存命中率:由缓存提供服务的占比,命中率与缓存大小,用户兴趣相似点,数据的变化,缓
唯一Chat
2019/09/10
4240
[日常] HTTP的缓存
缓存从入门到放弃
缓存就是数据交换的缓冲区(称作Cache),这个概念最初是来自于内存和CPU。当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行
前端黑板报
2018/12/21
9520
php中header的几种用法
(一) 在PHP中用header("location:test.php")进行跳转要注意以下几点, 1、location和“:”号间不能有空格,否则会出错。 2、在用header前不能有任何的输出。 3、header后的PHP代码还会被执行。
botkenni
2022/01/10
5940
HTTP之缓存控制
http://www.nirsoft.net/utils/chrome_cache_view.html
Ashen
2020/06/01
6350
HTTP之缓存控制
跟我一起探索 HTTP-HTTP缓存
可复用性有几个优点。首先,由于不需要将请求传递到源服务器,因此客户端和缓存越近,响应速度就越快。最典型的例子是浏览器本身为浏览器请求存储缓存。
用户1418987
2023/10/16
4070
跟我一起探索 HTTP-HTTP缓存
【HTTP】缓存
随着用户访问量越来越大,缓存变得越来越重要。HTTP文件缓存可以减少冗余数据的传输;缓解网络瓶颈;降低对原始服务器的请求;以及降低距离延迟。
奋飛
2019/08/14
6860
HTTP缓存
HTTP 缓存不是必须的,但重用缓存的资源通常是必要的。它可以减少服务器的压力,如果不使用缓存,每次发起请求都要求服务器发送相应数据,很多时候服务器发来的内容并没有发生变化,就会“浪费”服务器带宽。可以在客户端设置缓存,给缓存加上过期时间,如果期限没到就是用本地缓存的内容。然而常见的 HTTP 缓存只能存储 GET 响应,对于其他类型的响应则无能为力。
多云转晴
2020/06/03
8610
强制缓存和协商缓存的区别
浏览器缓存(Brower Caching)是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。
用户9914333
2022/12/14
1K0
强制缓存和协商缓存的区别
网页性能优化浅谈与实践
描述: 当我们访问某一个网页时浏览器第一次加载网页时,会将页面资源存储在 HTTP缓存中。下次浏览器访问该页面时,它可以在高速缓存中查找以前获取的资源,然后从磁盘检索它们,其速度通常比从网络上下载它们的速度快。
全栈工程师修炼指南
2022/09/29
6600
网页性能优化浅谈与实践
强缓存与协商缓存
浏览器缓存是浏览器在本地磁盘对用户最近请求过的资源进行存储,当访问者再次访问同一资源时,浏览器就可以直接从本地磁盘加载资源,通过缓存的方式就可以减少与服务器的数据传输,减少服务器的负担,加快页面响应速度等。
WindRunnerMax
2020/08/27
1K0
IE内核浏览器的404页面问题和IE自动缓存引发的问题
本站404页面被IE替换成IE自己的404页面 在权限设置正确的情况下,自定义的404页面文件大小如果小于512字节,那么IE内核的浏览器会认为你自定义的404页面不够权威,从而使用其自带的404页面
mcq
2018/06/20
1.8K0
HTTP缓存机制与Cookie
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当Web缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。
Dreamy.TZK
2020/08/11
1.3K0
HTTP缓存机制与Cookie
HTTP 的缓存为什么这么设计?
作为前端开发,缓存是整天接触的概念,面试必问、工作中也频繁接触到,可能大家对缓存的 header 记的比较熟了,可是大家有没有思考过为什么 HTTP 的缓存控制要这么设计呢?
神说要有光zxg
2022/06/06
2160
HTTP 的缓存为什么这么设计?
相关推荐
Web 开发人员需知的 Web 缓存知识
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验