Facebook团队关于网页缓存的再次实践
译者前言
8年前,Yahoo团队曾对网页缓存进行了较为详尽的研究。然而,随着互联网的高速发展,相关研究数据已发生变化。本文主要是Facebook的Web团队针对当前网页缓存情况所开展的数据收集与研究,涵盖PC和移动端资源的缓存时间以及资源的存在时间。网页缓存是性能优化的关键因素,值得深入研读。由于译者能力有限,若存在翻译错误,欢迎随时交流指正。
正文
网页加载速度是每个网站都应高度重视的因素,但往往容易被忽视。缓存是提升网站访问速度的重要手段,因为用户下次访问时无需重新计算或下载已缓存的资源。
Facebook Web团队近期针对facebook.com无缓存的现状展开讨论,核心问题包括:在Facebook每天发布两个版本的情况下,如何提高缓存效率?何种缓存策略最为适用?
在寻找解决方案的过程中,团队发现雅虎性能优化研究博客上已有一篇相关的性能研究文章。令人惊讶的是,该研究显示20%的页面访问是在空缓存状态下进行的。不过,这项研究距今已有8年,当时IE7和jQuery的首个版本刚刚发布。因此,团队决定重新开展研究,以了解当前情况是否有所改善。
重新研究
在之前的研究中,Yahoo在服务器端设置HTTP头,指定图片的过期时间和上次修改时间。若图片未发生改变,浏览器会通过GET请求向服务器发送最后修改时间的信息。若图片未修改,服务器将返回304(未修改)状态码,替代200(请求成功)。Yahoo利用服务器日志统计缓存用户数量,因为服务器能够记录浏览器请求的状态。
借鉴类似的研究方法,团队创建了一个PHP端点,既能发送图片请求,又能在数据库中记录日志。该图片通过HTTP头信息控制浏览器缓存以及代理产生的缓存,并在用户请求图片时记录相关信息。
图片HTTP头信息的设置如下: (此处原文设置内容缺失,需补充完整才能准确展现)
但由于IE7和IE8存在已知的BUG,团队对两个属性进行了如下替换: (此处原文替换内容缺失,需补充完整才能准确展现)
当浏览器向图片发送请求时,会出现以下两种情况:
- 若浏览器首次打开该图片,无额外头信息,服务器将返回状态码200 Success,并返回图片数据。之后,浏览器会缓存文件HTTP头信息中的Last-Modified(文件最后修改时间)和ETag(被请求变量的实体值)。
- 若浏览器之前打开过该图片,会检查if-none-match或if-modified-since头信息。若满足条件,将不加载图片数据,直接返回Status: 304 Not Modified(未更新)。同时,团队将Last-Modified头信息用$header['if-modified-since']替换$now(),确保每次返回内容一致。
最终,团队决定在Facebook的搜索条下方添加一个img标签,使每次Facebook加载时都会渲染该图片。在页面重新加载时,资源将依据缓存头信息进行加载,这是测试想法的最佳方式。在确保端点能正常记录请求、图片标签可正常访问后,研究正式启动。
研究结果
经过数周的数据收集,团队选取了最后7天的有价值数据进行分析。统计结果令人意外,仍有25.5%的请求为空缓存。为使数据更清晰,团队分别统计了PC和移动端的数据,结果相近:PC端空缓存请求占比24.8%,移动端为26.9%。这一结果与预期不符,团队遂深入研究数据。
将PC端浏览器分开统计后发现,用户使用Chrome和Opera时缓存几率更高。图表中未包含Firefox浏览器的数据,原因是Firefox 31及更早版本的缓存概率达80%,但32及更高版本显著下降,这是由于其缓存策略与统计方法存在冲突(参考链接:http://www.janbambas.cz/new-firefox-http-cache-enabled/ ),因此团队剔除了该浏览器的数据。
移动端数据显示,大部分浏览器的缓存比例在68% - 84%之间,不同移动平台的数据差异较大,推测可能与低端移动设备有关。移动端和手机端空缓存用户的平均占比为44.6%,与Yahoo团队2007年的研究结果相符。
更进一步
在Facebook,产品迭代速度极快,每天几乎发布两个版本。这促使团队思考,何种缓存时间设置最为合适。团队通过将if-modified-since文件头返回的时间减去当前时间来寻找答案。
依据此方法,团队统计了从首次正常请求到出现304请求的时间,即用户从无缓存到有缓存的时长,并生成了相关图表。
图表的横轴表示以小时为单位的时间,垂直竖线P50和P75分别代表某一时间内缓存请求的占比。例如,P50表示在47小时时,50%的请求有缓存;P75则意味着75%的请求有缓存。移动端测试数据显示,约12小时时,50%的请求有缓存。
实际应用
总体而言,本次统计结果与2007年的研究较为相似。若不计入Firefox 32及更高版本的数据,本次有缓存的比例最高点达84.1%,高于2007年的80%。
然而,缓存的存在时间并不长。研究表明,新版本发布47小时后,虽有42%的请求带有缓存,但缓存资源在电脑上的存在时间大致相同。这一发现对其他网站具有重要的参考价值。
缓存存在时间不长的原因不难理解。从互联网发展来看,网站体积自2007年以来变化显著。2007年,家庭网速约为2.5M,Yahoo首页大小为168.1KB;如今,手机下行速度可达8G,Yahoo首页已增至768KB,网页平均大小超1MB。这给浏览器的正常运行带来巨大压力(注:因需缓存的资源过多,当超过浏览器默认的资源缓存大小时,早期缓存文件会被自动删除,如IE默认缓存大小为50MB,Chrome为320MB)。
因此,合理利用浏览器缓存比8年前更为重要。最佳实践建议:尽量采用外链样式表和JS,在headers中设置Cache-Control和ETag,尽可能压缩数据,用不同网址管理缓存,分割需要频繁更新的资源。这些优化方法不仅适用于Facebook这类大型项目,其他网站也可借鉴。尽管更新频率会对缓存优化产生负面影响,但这并非本文的研究重点。实际上,Facebook已开始运用本次研究成果,让所有访问用户受益。