Cache友好型的url构造方法
作者: linyu, Last Updated: 03/09/11 09:34:44
写这篇文章的目的:在日常的工作中,经常有同事来询 问有关缓存的问题,例如这样的url会不会被缓存、缓存期多长等;另一方面,也在生产环境的Cache服务器上发现很多不可缓存的引用,既降低了Cache效 率,又增加了服务器负担。所以,希望借此文把一些经验总结向大家分享一下,设计页面url的同学们 如果可能的话,就可以在以后的工作中尽量避免出现自己“攻击”自 家的Cache的情况。好了话不多说
1. 缓存的意义
首先老生常谈一下缓存的意义,不 外乎:
1.1. 减少对网络带宽的占用
1.2. 提高访问速度,提升用户的体验
1.3. 减轻网站服务器的负担
几乎所有的大型网站都启用了Cache和CDN来分担用户流量,腾讯和淘宝的CDN流量是以百G计的,不难想象假如没有CDN缓存,这些网站在数百G流量的压力下是什么样的 情况。即使对B2B这样相对“小”的网站来讲,静态文件的流量也有好几个G,做好文件 缓存的规划对我们的意义也是非常重要的,从源头做起比积重难返时再改造来得有智慧。
OK意义谈完了,接下来步入正题。
2. 静态文件url应该长什么样
下面主要讲讲好的静态url设计应该是什么样的,哪些设计可能会造成Cache不 友好。
既然需要缓存,必然涉及缓存时 间,所以HTTP header中应该有>30天 的Expires/Cache-control头。有了这个过期头,缓存服务器、CDN才会缓存数据,否则只能靠配置默认规则了。You know, 默认规则是考虑了大多数的妥协的结果,不是最好的结果。这一点大家可以去看新浪、搜狐、QQ、淘 宝,他们的静态文件过期时间是在什么时候,可以告诉大家是在2012年到2021年之间。
设置方法很简单,在apache添加Expires模块就行了,手册网上 很多。
这里的更新指“同名更新”,有人可能会问,缓存的文件我要更新怎么 办?这个问题与缓存本身是矛盾的,解决方法很简单:不更新。例如,`http://mat1.qq.com/js/speed_v1.9-min.js`是腾讯门户页面上的一个js,他们要更新这个js会怎么办呢,想必大家都看得 明白不会去修改speed_v1.9-min.js这个文件,而是会生成speed_v2.0-min.js
避免同名更新,使文件版本化,这 就是最佳答案。最近发现国际站的文件长过期版本化已经有很大进展了,例如`http://i00.i.aliimg.com/images/eng/style/icon/icon_atmonline_v2.gif`——相信下次修改会是v3.gif
经常变化的随机数是缓存的敌人, 特别是每次请求都不一样的随机数。刚刚在缓存服务器上挖掘出一个这样的url,降低了命中率十几个 百分点:`http://www.example.com/sfm/app/uploader_v2/uploader.swf?__updateTime1299549287375 `,明 显最后的字符串是与时间相关的随机数,每次用户访问,这个数都会不同(具体原因可参考哲学名言“不 可能两次踏进同一条河流”),那么缓存就没有意义了:缓存的数据以后是没有第二次请求的,存了没 用;要么不缓存?那就不必要通过缓存服务器了。
如果是类似这样的url呢`http://www.example.com/css/3v/component.css?t=070904.css` ,理论上讲这种是可以的,它可能 是把这个css文件的修改时间作为一个参数放在末尾,除非下次修改否则数字永远不变。但是这种方法 与动态脚本上传参数的方式无法区分,如果有动态脚本被缓存比如login的结果,阿猫会发现自己登 到阿狗的帐户去了。所以万全之策是两种方法都不使用。
大家可以参观一下这个url:
http://unic.alibaba.com/app/script_loader/script_loader|run/intl_searchweb/alitalk|lib/yui/connection/connection-min\
|run/intl_searchweb/listSearchbar|run/intl_searchweb/list_page_select|run/intl_searchweb/yahoo_dms_create|r20101008|\
app/p4p/express|app/p4p/express_next|app/p4p/express_prev|app/navigator/navigator|v214171345.js
没有耐性数数,复制下来wc了一下,328个字符。再对比一下刚才提到的腾讯`http://mat1.qq.com/js/speed_v1.9-min.js`,40个字符。在这里不是对这个url进行批判,相信这 么长有它的道理,只是用这个极端的例子说明一个对比,假设我们的网站有10000个并发(高峰期实 际不止),不考虑请求的文件是什么,仅仅我们的请求本身消耗的带宽是328byte*10000*8bit/byte=26Mbps。 如果同样缩减到40个字符,则带宽消耗就变成3Mbps了, 差别还是有的,保证功能的前提下就短不就长。
现在咱们网站的cookie是500-700字节,计算取平均值600byte,与上一条同理,用户请求我们的文件需要发送cookie,10000的并发数,仅请求本身消耗带宽就是48Mbps。cookie是页面必须的东西不能少,但是对于图片文件和css这 类文件来讲,cookie就完全多余了,所以静态文件避免cookie既 可以加快请求速度(不必send 600byte了),又可以减少服务器接收处理cookie的额外开销,何乐而不为呢?方法也很简单,把静态文件的域名改为无cookie的域就可以了。
这一点来源是rfc规范里规定了浏览器在一次页面请求中,对同一个域名最多发起2个 并发,顺理成章的,人们就想出了增加域名的方法来绕过这个限制。拆分域名这一条在以前浏览器仅支持一个域名两个并发的年代是比较重要的,可以增加文件下载 的并发数,提高页面load速度。但是现在的IE8、FF3等浏览器都支持超过2个的并发,FF3是6个并发,IE8甚至能够支持到18个并发,以增加并发为目的的 诉求并不是那么大了。
另一方面,拆分域名和控制域名数 量是一个平衡的过程,页面上域名的数量不能太多,否则花在DNS解析上的时间也不少,雅虎牛人出的 著名网站优化“14条”中说静态域名不要超 过4个,就是从DNS解析效率方面出发的。 其实在浏览可以支持大并发的前提下,这一点已经不太重要,建议结合上面提到的“避免cookie”的那条规则,酌情定数量。
3. 总结
不知不觉列了这么多,基本上都是 平时工作中遇到的问题的总结,共享给大家作为参考。上面提到的很多东西都要倚仗咱们的开发、ued工 程师来完成,这里只是结合了通行的优化做法和网站实际情况提供了一些建议,期望在以后新建站点、开发新业务时可以避免历史的错误。共同将网站速度优化这件 事情做好。
这篇文章会放在运维部的文档系 统,并且保持更新,欢迎偶尔莅临参观。