扼杀 304,Cache-Control: immutable

随着近些年社交网站的流行,越来越多的人学会了“刷”网页 ── 刷微博,刷朋友圈,刷新闻,刷秒杀页。这里的“刷”,就是刷新的意思,在浏览器里,你可以通过点击刷新按钮,或者用快捷键,或者移动端的下拉操作来进行刷新。

但普通网民不知道的是,通过刷新操作导致的页面加载和通过其他操作(比如点击页面链接,地址栏输入网址并回车,点击收藏夹网址等)导致的页面加载有一点不同,那就是刷新操作会给该页面的请求本身以及页面里所引用的资源们(JS,CSS,图片等)的请求加上 If-Modified-Since 和 If-None-Match 请求头(如果已经有缓存且有 Last-Modified/ETag 响应头的话),服务器会根据这两个请求头判断该资源有没有更新过,如果没有,就返回不带响应体的 304 响应,告诉浏览器:“用缓存吧”,如果更新过了,则把更新后的资源放在响应体里返回 200 响应。

我们把上面说的这种带有 If-Modified-Since 或 If-None-Match 请求头的 HTTP 请求叫做条件请求,除了刷新操作,条件请求还会发生在缓存过期的时候,也就是已缓存时长大于 Cache-Control 响应头中的 max-age 字段指定的秒数的时候。

条件请求是设计用来更新资源的,但实际情况是,在现如今的网站开发中,尤其是大型网站,会依赖适当的过期时长或者让用户手动刷新来更新页面吗?比如把缓存时长设置成一小时,新版页面上线了,用户都看不到效果,老板过来问:“这怎么回事啊,不是上线了吗”,开发回答:“要等一小时缓存过期啊,你也可以刷新一下就看到效果了~”。显然不可能这样,对于那些有更新需求的静态资源,常见的是 JS、CSS,我们都会在它的 URL 里加上点东西,时间戳、版本号、哈希值等,可以放在 URL 的路径里,也可以放在查询参数里,因为只要 URL 变了,浏览器就认为是不同的资源,就会重新下载;还有一些静态资源是完全没有更新需求的,比如你在微博上传的那些图片,同一个 URL 对应的资源是永远不会变的。

上面说的这两种情况,其实是一种,就是它们永远没有更新的需求,它们是不可变的,是 immutable 的,304 用在它们身上完全没有意义,全是浪费。虽然每个 304 请求的往返体积只有 1k 左右,但架不住多啊。而且就算只有一个字节,也会导致页面展现变慢,读本地文件和读网络资源还是有本质区别的。

Facebook 在一年前意识到了这个问题,它的工程师给制定 HTTP 标准的 IETF 工作组发了封邮件,里面说到,Facebook 使用版本号来更新静态资源,还给静态资源设置了几乎不可能过期的缓存时长,但发现仍然有 20% 的请求是无意义的条件请求(必然 304),这给服务器性能带来很大伤害,他们研究发现是因为 Facebook 页面 pv 有 2% 来自用户的刷新操作,他们希望 HTTP 协议能给 Cache-Control 响应头增加一个属性字段表明该资源永不过期,浏览器就没必要再为这些资源发送条件请求了。

今年四月份,Mozilla 的人觉的 Facebook 提的这个建议很好,于是他们在 Firefox 49 里实现了 Cache-Control: immutable。immutable 的推荐用法是和那些超大的 max-age 配合使用,比如 1年:Cache-Control: max-age=31536000, immutable,甚至 10年, 但通常情况下,1 年就够了,因为:1. 对于单个缓存来说,它在某个浏览器里存活的时长不可能超过一年,浏览器的缓存空间都有上限,Firefox 256M,Chrome 320M,旧的缓存会时不时被清掉。2. 一个用户不大可能一年后还来同一个页面,且那个页面还没改版。对缓存时长来说,1 年就代表永远了。

但这只是推荐做法,immutable 并不是真的只能应用在那些永不过期的资源上,也可以配合较小的 max-age 来使用,比如一些个人博客,或者一些不太讲究及时更新的站点,可以设置成 Cache-Control: max-age=3600, immutable,表明该资源能存活一小时,在一小时之内,即便用户刷新也不要发送条件请求,在过期之后,浏览器会发送不带一个不带 If-Modified-Since 和 If-None-Match 的请求来更新资源,这里需要注意,一旦被标志成 immutable,则这个资源不可能返回 304 响应了,只有 200。

目前 Firefox 的实现里,只对 HTTPS 资源开放 immutable 属性的支持,我通过 Fiddler 在本地篡改了淘宝搜索页面 https://s.taobao.com/search?q=连衣裙 里所有资源的 Cache-Control 响应头,在原值尾部加上 “, immutable”。篡改之前,假如我刷新一下此页面,会导致数十个 304 响应:

篡改之后的刷新效果:

注意那些带有 cached 字样的 200 请求,那些请求实际上根本不是真正的请求,只是一次本地读取文件的操作。

目前 Facebook 还没有反馈 immutable 的测试数据,毕竟 Firefox 49 还不是正式版,以后应该会有的。不过考虑到现在 Firefox 的市场占有率,也许 Chrome 实现之后才会得到更多人的关注, Chrome 也表示了有意愿去实现。不过我在 GitHub 搜了一下,倒是发现 W3C 的网站Firefox 附加组件网站准备实现。

immutable 只有在你的网站被频繁刷新的情况下才有较大的意义。还有虽然它是向后兼容的,但可能一些 CDN 服务器在识别 Cache-Control 时因不认识这个属性,导致最终返回给浏览器的响应丢失了 immutable,推特上有反应 Akamai 就这么干了。

少数人知道的强制刷新功能(Ctrl+F5/Shift+Command+R)以及开发者工具的跳过缓存功能优先级应比 immutable 更高。

时间: 2024-10-25 14:14:37

扼杀 304,Cache-Control: immutable的相关文章

etag cache control

https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn 我们唯一要做的就是确保服务器提供必要的 ETag 令牌.检查您的服务器文档中有无必要的配置标志.有没有etag是服务器配置, 每个资源都可通过 Cache-Control HTTP 标头定义其缓存策略 Cache-Control 指令控制谁在什么条件下可以缓存响应以及可以缓存多

Partitioned Replacement for Cache Memory

In a particular embodiment, a circuit device includes a translation look-aside buffer (TLB) configured to receive a virtual address and to translate the virtual address to a physical address of a cache having at least two partitions. The circuit devi

HTTP请求中的缓存(cache)机制

http://www.chaorenmao.com/blog/?p=79 流程 当资源第一次被访问的时候,HTTP头部如下 (Request-Line)  GET /a.html HTTP/1.1Host    127.0.0.1User-Agent  Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15Accept           

Symfony2学习笔记之HTTP Cache

富web应用程序的本质意味着它们的动态.无论你的应用程序多么有效率,每个请求比起静态文件来说总会存在很多的耗费.对于大多数web程序来说,这没什么. Symfony2非常的轻快,无论你做些严重超载的请求,每个请求将会得到很快的回复,而不会对你的服务器造成压力.但是随着你站点的成长,负载将成为一个严重的问题.对每个请求处理应该只被正常执行一次.这就是缓存真正要达成的目标. 站在巨人肩膀上的缓存:提高一个应用程序执行效率的最有效方法是缓存一个页面的所有输出然后让后续的请求绕开整个应用程序.当然,这对

CDN之Web Cache

1. Cache 的工作方式 Web Cache 作为一种网页缓存技术,可以在用户访问网站服务器的任何一个中间网元上实现.根据 HTTP 协议的定义,在一次网页访问中,用户从客户端发出请求到网站服务器响应请求内容的交互过程中,通常会涉及 4 个关键的网元:用户.代理.网关和 Web 服务器.当 Web Cache 作为代理使用时,通常工作在正向代理或者透明代理的模式,Web Cache 可以在这两种模式下实现访问内容副本的缓存和服务:Web Cache 应用最多的地方还是在网关上,这也是 CDN

Method, apparatus, and system for speculative abort control mechanisms

An apparatus and method is described herein for providing robust speculative code section abort control mechanisms. Hardware is able to track speculative code region abort events, conditions, and/or scenarios, such as an explicit abort instruction, a

Extensible Access Control List Framework

Methods, systems, and products for governing access to objects on a filesystem. In one general embodiment, the method includes providing a framework in an operating system environment for support of a plurality of access control list (ACL) types, the

PSEUDO LEAST RECENTLY USED (PLRU) CACHE REPLACEMENT

A multi-way cache system includes multi-way cache storage circuitry, a pseudo least recently used (PLRU) tree state representative of a PLRU tree, the PLRU tree having a plurality of levels, and PLRU control circuitry coupled to the multi-way cache s

httpcomponents-client-4.4.x

Chapter 1. Fundamentals Prev     Next Chapter 1. Fundamentals 1.1. Request execution The most essential function of HttpClient is to execute HTTP methods. Execution of an HTTP method involves one or several HTTP request / HTTP response exchanges, usu