【问题标题】:Is my PHP script cache (public) friendly?我的 PHP 脚本缓存(公共)是否友好?
【发布时间】:2010-12-31 05:14:30
【问题描述】:

我已经完成了一个可以为许多文档提供服务的小型 PHP 应用程序。这些文档必须可由客户端代理缓存。

由于代理可以缓存我的结果,我必须格外小心,因为我服务的文档可以有不同的 MIME 类型(基于 $_SERVER['HTTP_ACCEPT'] 的内容协商)和不同的语言(基于此顺序:$_POST 值 / $_GET 值/URL/PHP 会话值/$_COOKIE 值/$_SERVER['HTTP_ACCEPT_LANGUAGE']/默认脚本值)。

简而言之,一个页面可以使用多种 MIME 类型多种语言提供相同 URL(问题已更改:请参阅下面的编辑)。

为了帮助缓存代理,我将“Vary: Accept”标头结合与 ETag 标头结合使用。 ETags 是当前语言的 MD5 和最后修改的时间戳。

我总是:

  • 发送过期标头
  • 发送 Cache-Control 标头
  • 发送 Last-Modified 标头
  • 发送 Content-Type 标头
  • 发送 ETag 标头(基于当前语言和 Last-Modified 时间戳)
  • 发送内容语言
  • 如果文档是 XHTML,则发送“Vary: Accept”标头

现在我的问题是:这足以帮助在代理客户端上进行缓存吗?我错过了什么/标题吗?

为了帮助您,这里是测试页面的 HTTP 响应标头(在我的本地环境中):

"
Date             Wed, 30 Dec 2009 18:56:26 GMT
Server           Apache/2.0.63 (Win32) PHP/5.1.0
X-Powered-By     PHP/5.1.0
Set-Cookie       Tests=697daqbmple2e1daq2dg74ur96; path=/
Expires          Wed, 30 Dec 2009 21:56:26 GMT
Cache-Control    public, max-age=10800
Last-Modified    Mon, 28 Dec 2009 15:11:49 GMT
Etag             "44fa50be4638161a596e4b75d6ab7a94"
Vary             Accept
Content-Language en-us
Content-Length   3043
Keep-Alive       timeout=15, max=100
Connection       Keep-Alive
Content-Type     application/xhtml+xml; charset=UTF-8
"

编辑:好的,我知道在这种情况下,提供一个包含许多 MIME 具有不同语言(可能来自这么多来源 - 见上文)的文档只是简单的糟糕设计。如果您想这样做,只需使用“私有”缓存(代理上没有缓存)...我正确吗?

如果每种语言都有自己的 URL(但每个 URL 仍然可以使用许多 MIME),我当前的实现是否适合“公共”缓存(客户端缓存 + 代理)?

【问题讨论】:

    标签: php http caching proxy http-headers


    【解决方案1】:

    由于您的输出还取决于代理无法知道的内容(例如会话数据),因此将(不可缓存的)重定向发送到实际内容会更容易吗,这对于给定的 URL(带有参数)是固定的因此更容易缓存。我知道这涉及到额外的往返,但它可能更不容易出错,并且对于不完全理解/支持所有标题组合的代理来说,也会减少问题。

    另外,我猜,如果您有两个客户端通过同一个代理但使用不同的语言 cookie,那么您当前的方法将为同一个 URL 返回两个不同的 ETag,这会使代理每次更新其副本它看到另一个客户端。

    【讨论】:

    • 会话/cookie 仅包含语言,并在 ETag 和 Content-Language 标头中发送...
    • 但是代理如何知道为其客户提供哪种语言?
    • 我现在明白了...你将如何在 PHP 中实现不可缓存的重定向?
    • 和你通常一样,就像header("Location: /document?lang={$_COOKIES['lang']}&format={$_POST['format']}")(带有适当的urlencoding等),默认情况下它是不可缓存的。或者,如果您控制生成包含指向 /document 链接的 HTML 的文档,则只需在第一次生成正确的带参数的 URL,您甚至不需要重定向。
    • 感谢您的帮助。在每种语言都有自己的 URL 的情况下,如果页面可以被代理和客户端(公共)缓存,我的标题是否合适?请参阅对原始问题的编辑。
    【解决方案2】:

    我相信您原则上应该没问题 - 添加 Vary 标头意味着缓存应该保存您的数据的多个实例,由 ETag 键入。

    不过,我要注意的是,您不仅在接受方面有所不同,还在 Cookie 和接受语言方面有所不同。因 cookie 而异意味着代理必须验证每个请求,但应该能够使用 If-None-Match 标头让服务器指示应该使用哪个(已经缓存的)ETag。

    【讨论】:

    • 我认为你是对的。当你有很多这样的条件时,Vary 标头的语法是什么?
    • 查看w3.org/Protocols/rfc2616/rfc2616-sec14.html 第 44 节。重新阅读您的 cmets,我认为您可能需要改变:*,因为在没有 cookie(或任何其他标题或 URL)的会话中语言可能会发生变化组件)变化。
    【解决方案3】:

    如果“Accept”和“Accept-Language”的响应都不同,则需要在“Vary”响应标头中提及两者。

    【讨论】:

    • 它基于由(按此顺序)设置的(级联)当前语言:$_POST 值/$_GET 值/URL/PHP 会话值/$_COOKIE 值/$_SERVER['HTTP_ACCEPT_LANGUAGE '] / 默认脚本值
    • 如果它在请求头之外的数据上有所不同,您需要声明“Vary: *”,或者将其取出并相应地设置 Cache-Control。否则中介会很困惑。
    猜你喜欢
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多