【译】Optimize caching-缓存优化

缓存优化


大部分的网页都包括不常更改的资源,比如CSS文件,图片文件,JavaScript文件等。这些资源通过网络下载需要一定的时间,这就增加了网页加载的总时间。HTTP缓存可以让这些资源通过浏览器以及代理服务器进行保存或缓存。一旦资源被缓存,用户再次访问这些页面时,浏览器或代理可以直接引用本地缓存的副本,而不必重新下载。因此,缓存是一个双赢的策略:你可以通过减少所需资源文件的http请求数来减少​往返时间,还可以大幅的减少响应的网络负荷。启用缓存除了可以有效的减少后续用户访问时页面加载时间,还可以显著减少网站带宽消耗和网站运维费用。

有效利用浏览器缓存

有效利用代理缓存

 

有效利用浏览器缓存


概览

在http请求头中对那些静态资源设置到期日期或最大有效期来指示浏览器不要请求网络而直接从本地磁盘加载先前下载的资源。

 

详细介绍

HTTP / S支持静态资源浏览器本地缓存。一些最新的浏览器(如IE 7,Chrome浏览器)使用一个启发式的方式来决定对那些没有明确的缓存头的资源缓存多久。其他较旧的浏览器在他们从缓存中提取资源时需要之前已经设置了缓存头,还有些不会缓存基于ssl来发送请求的任何资源。 

要想从所有浏览器中充分利用高速缓存带来的收益,我们建议您通过配置Web服务器显式的对所有需要缓存的静态资源设置缓存头,而不仅仅是一小部分(如图片)。可缓存的资源包括JS和CSS文件,图片文件,和其他二进制目标文件(媒体文件,PDF文件,Flash文件等)。一般情况下,HTML不是静态的,而不应被视为可缓存的。 

HTTP/1.1提供了以下缓存响应头:

  1. Expires和Cache-Control:max-age。这两个指定了资源的“新鲜度”,就是说在这段时间,浏览器可以使用缓存的资源而不用检查它们在服务器上是否有可用的新版本。他们是无条件的 “强缓存头”,也就是说,一旦设置过并且资源被下载以后,在截止时间之前,浏览器不会对这些资源发出任何GET请求。

  2. Last-Modified和ETag。浏览器通过这些特性检查并确定这些文件是否是没变的。Last-Modified 头始终是一个日期。ETag头可以是任意值,它能够唯一的标识一个资源(文件版本或内容的哈希值)。Last-Modified是 “弱”缓存头,浏览器参考它来确定是否从cache中获取项目缓存。(不同的浏览器处理方式不一样。)尽管如此,当用户刷新重载页面时,这些头允许浏览器有条件的发出GET请求。除非服务器上这些资源文件已经改变了,否则这些有条件的GETs不会返回完整的响应,这样还是比完整的GETs延时要小。

对所有的可缓存资源指定一个Expires 或Cache-Control:max-age, 同时指定一个Last-Modified 或ETag非常重要。同时指定Expires 和Cache-Control:max-age,或同时指定Last-Modified 和ETag是没必要的。 

 

建议

积极为所有静态资源设置缓存头。

对于所有的可缓存资源,我们建议进行以下设置:

  1. 设置Expires 的最短1个月,最好是长达一年。(我们更愿意用Expires而不是Cache-Control:max-age的,因为它可以得到更广泛的支持。)不要将其设置为超过一年的时间,这违反了RFC指导原则。

    如果你明确地知道一个资源什么时候会更新,设置较短的到期时间就好。但如果你认为它“可能会很快改变”,但不知道什么时候,你应该设置一个较长的到期时间并且使用URL指纹(下面会介绍)。积极设置缓存不会“污染”浏览器缓存:据我们所知,所有的浏览器都使用最近最少使用算法来清理缓存,我们没有发现有任何浏览器会一直等到资源文件已过期时才清理缓存。

  2. 将Last-Modified设置为资源最后一次资源修改的日期。如果Last-Modified日期是很久很久以前,没准浏览器不会再去读取它。

使用指纹识别动态启用缓存。

对于偶尔更改的资源,你可以让浏览器一直缓存着,直到服务器端文件已经做了更改,此时服务器告诉浏览器,一个新的版本可用。您可以在该资源的URL(即文件路径)中添加指纹。当资源发生了变化,它的指纹也发生了变化,从而它的url也发生了变化。一旦URL发生变化,浏览器被强制重新获取该资源。指纹允许您把到期时间设置的非常长,尽管这段时间可能变换的比较频繁。当然,这就要求,所有引用该资源的页面知道该url,是否可行主要取决于你的页面代码是怎么写的。

IE设置正确的Vary头。

Internet Explorer不会缓存任何设置了Vary头的资源,除了Accept-Encoding和User-Agent。为了确保这些资源能够被IE浏览器缓存,一定要从Vary头去掉其它东西,如果可以的话直接删除Vary头。

避免引起firefox缓存冲突的URLs

Firefox的磁盘缓存哈希机制可能引起那些只有轻微差别,也就是只有8个字符范围的差异的URLs产生缓存冲突。当资源散列到相同的关键字,只有一个资源被保存在磁盘上进行缓存;当浏览器重启动后使用相同关键字的其它资源必须重新获取。因此,如果您使用的是指纹或者其他程序生成的文件的URL,为了最大限度地提高缓存命中率,避免Firefox的哈希冲突的问题,必须确保您的应用程序生成的URLs至少有8个以上字符的不同。

使用Cache control:在firefox中直接用public启动https缓存。

火狐的一些版本要求使用Cache control:public头来设置让那些通过SSL发送的资源请求在磁盘上缓存,尽管已经显式的设置了其它缓存头。虽然这个头通常用来指定代理服务器启用缓存(如下文所述),代理服务器不能缓存通过任何通过HTTPS发送的请求,所以设置这个头对HTTPS资源始终是安全的。

 

例子

比如一个用来显示用户登陆后的日历的样式表,谷歌日历其文件名内嵌入指纹:calendar/static/fingerprint_keydoozercompiled.css,这里的指纹密钥是128位十六进制数。看下面的屏幕截图(来自Page Speed的Show Resources面板),指纹设置为82b6bc440914c01297b99b4bca641a5d:

Optimize caching-例子

指纹识别机制允许服务器设置Expires头为请求的日期刚好一年;Last-Modified头为日期文件的最后修改日期;Cache-Control:max-age头为3153600。为了使客户端能够在服务器文件变更时重新下载,而不用等到过期时间或最长有效期,文件内容改变的情况下同时改变指纹(URL也是)即可。

 

其他资源

  1. For an in-depth explanation of HTTP caching, see the HTTP/1.1 RFC, sections 13.2, 14.21, and 14.9.3.
  2. For details on enabling caching in Apache, consult the Apache Caching Guide.

 

有效利用代理缓存


概览

静态资源可以利用HTTP头的公开缓存让浏览器不用从远程原始主机下载而直接从附近的代理服务器下载。

 

详细介绍

除了浏览器缓存,HTTP提供了一种代理缓存,是静态资源被缓存在ISPs的公共web代理服务器上。这意味着,即时是初次访问你的碗盏的用户也可以从中获益:一旦某个用户通过代理服务器访问一个静态资源,这个资源对于其它通过这个相同的代理服务器访问的用户来讲都是可用的。由于这些代理服务器的网络位置可能是相对于你的服务器来讲跟用户更进阶,代理缓存可能显著减少网络延迟。此外,如果启用代理缓存相当于为您提供免费网站托管,因为代理缓存的响应根本就不会占用您的服务器的带宽。

您可以使用Cache-control:public头去标明一个资源请求除了被浏览器缓存,还可以被公共网络代理服务器缓存。除了一些特殊情况(如下所述),你应该配置Web服务器,将这些可缓存资源的这个头设置为public。

 

建议

请不要在静态资源的URL中查询字符串。

大多数代理,特别是Squid 3.0版以上的服务器,不会缓存那些在url中带了“?” 的资源,尽管在相应中设置了Cache-control:public。要使这些资源可以被代理缓存,需要删除查询字符串,可以将它们编码到文件名中去。

对设置cookie的资源不要启用代理缓存。

为了在多个用户之间共享资源而设置这些头,这意味着这些资源的任何cookie也都是共享的。虽然许多代理服务器并不会缓存那些设置了cookie头资源,但最好还是要完全避免不必要的风险。无论是将Cache-Control头设置为private还是将这些资源放到一个无cookie域中都可以。

注意JScss文件的代理缓存的问题。

一些公共代理服务器存在这样的问题,它检测不到Content-Encoding响应头的存在。这可能会导致压缩版本资源被传递到客户端浏览器,但浏览器不能正确地解压缩。由于这些文件可能在你服务器使用gzip压缩,为确保客户端可以正确读取这些文件,请执行以下操作:

  1. 将Cache-Control头设置为private。这将使代理缓存不能缓存这些资源。如果你的应用程序遍布全球各地,本地用户很少依赖代理缓存,这可能是一个适当的设置。
  2. 设置Vary:Accept-Encoding响应头。这将指示代理缓存两个版本的资源:一个压缩的,一个未压缩的。根据客户端的请求头传递正确压缩格式的版本。这对于那些应用程序是单点分布,本地用户依赖代理缓存的情况是个不错的选择。

 

查看英文原版

posted @ 2014-04-02 09:19  rockyli  阅读(362)  评论(0编辑  收藏  举报