浏览器缓存控制,动态内容

3

问题: 我似乎无法让FireFox缓存从动态服务器发送的图片

设置: 静态Apache服务器通过反向代理到后端的动态服务器(mod_perl2)。

这里是服务器的请求URL。它被发送到动态服务器,其中Cookie用于验证对图像的访问权限:

请求头

Host:  <OBSCURED>
User-Agent:  Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15
Accept:  image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive:  300
Connection:  keep-alive
Referer: <OBSCURED>
Cookie:  pz_cred=4KCNr0RM15%2FJCOt%2BEa6%2BL62z%2Fxvbp2xNQHY5pJw5d6Q
Pragma:  no-cache
Cache-Control: no-cache

动态服务器将图像发送回服务器,并提供以下响应:
响应头:
Date:  Tue, 24 Nov 2009 04:28:07 GMT
Server:  Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0
Cache-Control: public, max-age=31536000
Content-Length:  25496
Content-Type:  image/jpeg
Via: 1.1 127.0.1.1:8081
Keep-Alive:  timeout=15, max=75
Connection:  Keep-Alive

到目前为止,一切都很好(我想)。然而,在重新加载页面时,图片不会被缓存,请求会再次发送:
请求头:
Host: <OBSCURED>
User-Agent:  Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15
Accept:  image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive:  300
Connection:  keep-alive
Referer: <OBSCURED>
Cookie:  pz_cred=4KCNr0RM15%2FJCOt%2BEa6%2BL62z%2Fxvbp2xNQHY5pJw5d6Q
Cache-Control: max-age=0

浏览器应该已经缓存了图片,所以不应该发生这样的请求。但事实上,服务器返回了一个200响应,就像第一次请求一样,看起来图片被重新获取了(虽然浏览器似乎确实在使用缓存的图片)。

问题似乎可以从上面reload请求头中的Cache-Control: max-age=0得到提示。

有人知道为什么会这样吗?也许是响应中的Via头引起了问题?

3个回答

5

原始请求已完成

Cache-Control: no-cache

这段文字的意思是,这条指令会告诉所有中间HTTP缓存(包括Firefox的)不要使用缓存的响应,而是从原始的Web服务器获取响应。 下一段话的意思是:
Cache-Control: public, max-age=31536000

这段文字告诉大家,就原始服务器而言,响应可能被缓存。服务器似乎已配置为允许PNG图像被缓存: HTTP 1.1(第14.21节)中提到:

注意:如果响应包含带有max-age指令的Cache-Control字段(参见第14.9.3节),该指令将覆盖Expires字段。

你的第二个请求是:
Cache-Control: max-age=0

该指令告诉所有中间HTTP缓存,您不会接受任何早于0秒的缓存响应。

需要注意的一点是:如果在Firefox中点击“重新加载”按钮,则要求从源Web服务器重新加载。要测试图像的缓存,请导航离开页面并返回,或在新标签中打开它。不确定为什么第一次看到no-cache,第二次看到max-age = 0。

顺便说一下,我喜欢Firefox的FireBug插件。您可以使用它查看请求和响应头以及各种其他好东西。


嗨Jim:感谢您的帮助!第一个请求来自Firefox,当我按shift-reload时。这似乎是合适的,因为我明确要求“新鲜”的内容。第一个响应也似乎是正确的;它具有预期的标头。第二个请求发生在浏览器重新加载/没有/ shift 的情况下。期望是Firefox缓存将遵守第一个响应,例如max-age=31536000。看起来服务器说所有图像(image/*)都是可缓存的。如果所有这些都是正确的,那么问题是什么使FireFox忽略缓存指令? - Michael Mikowski
我应该补充一下,在FireFox中启用了缓存,并且成功地从静态服务器缓存了图像。我还删除了via头,但是没有效果。 - Michael Mikowski

3

我的上一个回答只是部分正确。

问题在于FireFox 3处理重新加载事件的方式。显然,它几乎总是从源服务器再次请求内容。因此,使用Cache-Control: max-age=0请求头。

Firefox 确实使用缓存的图像来重新渲染页面,但然后它仍然会在“后台”中进行所有请求以更新它们。然后,它会在它们到达时替换它们。

因此,页面呈现速度快,YSlow报告缓存的内容。但服务器仍然会受到影响。

解决方案是在动态服务器脚本中询问传入的标头,并确定是否提供了“If-Modified-Since”标头。如果是这种情况,并且确定内容没有更改,则返回HTTP_NOT_MODIFIED(304)响应。

这不是最理想的解决方案 - 我宁愿Firefox根本不发出请求 - 但它可以将页面加载时间减半,并大大减少带宽使用。鉴于Firefox在重新加载时的工作方式,这似乎是最佳解决方案。

其他评论:Jim Ferran关于离开页面并返回的观点有其价值 - 缓存总是被使用,并且没有请求出去(+1到Jim)。此外,在初始加载之后动态添加的内容(例如AJAX调用)似乎也使用缓存。

希望这能帮助除我之外的其他人 :)


1

看起来问题已经解决了:

  • 通过头部删除代理
  • 添加了一个Last-Modified头部
  • 添加了一个远期过期日期

Firebug仍然显示来自源服务器的200响应,但是YSlow将图像识别为缓存。根据YSlow的说法,当新鲜时,总图像下载大小大于500K;在缓存准备好后,它显示0K的下载大小。

这是来自执行技巧的源服务器的响应头:

Date: Tue, 24 Nov 2009 08:54:24 GMT
Server: Apache/2.2.11 (Ubuntu) mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0
Last-Modified: Sun, 22 Nov 2009 07:28:25 GMT
Expires: Tue, 30 Nov 2010 19:00:25 GMT
Content-Length: 10883
Content-Type: image/jpeg
Keep-Alive: timeout=15, max=89
Connection: Keep-Alive

由于我请求图像的方式,这些日期是否静态其实并不重要;我的应用程序在请求图像之前就知道了最后修改时间,并将其附加到客户端请求 URL 上,以创建每个图像版本的唯一 URL,例如 http://myserver.com/img/125.jpg?20091122(信息来自 AJAX JSON 源)。例如,我可以将最后修改日期设置为 2000 年 1 月 1 日,过期日期设置为 2050 年某个时间。

如果 YSlow 是正确的——而性能测试表明它是正确的——那么 FireBug 真正应该报告这些本地缓存命中,而不是一个 200 响应。


我已经向FireBug报告了一个错误,关于本地缓存报告的200个响应。 - Michael Mikowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接