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 响应,与第一个响应相同,并且图像似乎被重新获取(尽管浏览器似乎正在使用缓存的图像)。

上面的重新加载请求标头中的 Cache-Control: max-age=0 似乎暗示了该问题。

有谁知道为什么会这样?也许是响应中的Via标头导致了问题?

4

3 回答 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 插件。您可以使用它查看请求和响应标头以及各种其他好东西。

于 2009-11-24T05:29:55.763 回答
3

我之前的回答只是部分正确。

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

Firefox确实使用缓存的图像在重新加载时呈现页面,但它仍然会发出所有请求以“在后台”更新它们。然后在它们进来时替换它们。

因此,页面渲染速度快,YSlow 报告缓存内容。但是服务器仍然被钉牢。

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

这不是最佳选择——我宁愿 Firefox 根本不发出请求——但它将页面加载时间减少了一半,并大大减少了带宽。鉴于 Firefox 在重新加载时的工作方式,这似乎是最好的解决方案。

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

希望这对我以外的人有帮助:)

于 2009-11-30T23:18:24.367 回答
1

看起来解决了它:

  • 通过标头删除代理
  • 添加了 Last-Modified 标头
  • 添加了一个遥远的到期日期

Firebug 仍然显示来自原始服务器的 200 个响应,但是,YSlow 将图像识别为缓存。根据 YSlow,新鲜时的总图像下载大小大于 500K;缓存启动后,它显示 0K 下载大小。

这是来自 Origin 服务器的响应标头,它可以解决问题:

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( info 来自 AJAX JSON 提要)。例如,我可以将最后修改日期设为 2000 年 1 月 1 日,并将到期日期设为 2050 年的某个时间。

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

于 2009-11-24T09:02:08.877 回答