我认为我的问题看起来很普通,但请耐心听我说,因为它变得有趣了(至少对我来说是这样的)。
考虑一个用途是从文件系统读取请求文件并将其作为响应输出的 PHP 页面。现在的问题是如何为此页面启用缓存?需要指出的是,这些文件可能非常大,启用缓存是为了使客户端免于不断下载相同的内容。
理想的策略是使用 "If-None-Match" 请求头和 "ETag" 响应头来实现反向代理缓存系统。即使我知道到这一步,我也不确定是否可能或者我应该返回什么响应以实现这种技术!
我认为我的问题看起来很普通,但请耐心听我说,因为它变得有趣了(至少对我来说是这样的)。
考虑一个用途是从文件系统读取请求文件并将其作为响应输出的 PHP 页面。现在的问题是如何为此页面启用缓存?需要指出的是,这些文件可能非常大,启用缓存是为了使客户端免于不断下载相同的内容。
理想的策略是使用 "If-None-Match" 请求头和 "ETag" 响应头来实现反向代理缓存系统。即使我知道到这一步,我也不确定是否可能或者我应该返回什么响应以实现这种技术!
使用PHP来服务大量或大型辅助文件并不是它的强项。
相反,对于nginx,可以查看X-accel,对于Lighttpd则是X-Sendfile,而Apache则是mod_xsendfile。
最初的请求由PHP处理,但一旦下载文件已确定,它将设置一些标头以指示服务器应该处理文件发送,此后PHP进程被释放以提供其他服务。
然后,您可以使用Web服务器为其配置缓存。
静态生成的内容
如果您的内容是从PHP生成的,并且特别耗费资源,请将输出写入本地文件并再次应用上述方法。
如果您无法写入本地文件或不想写入,则可以使用HTTP响应标头来控制缓存:
Expires: <absolute date in the future>
Cache-Control: public, max-age=<relative time in seconds since request>
这将导致客户端缓存页面内容,直到页面过期或用户强制重新加载页面(例如按下F5键)。
动态生成的内容
对于动态内容,您希望浏览器每次都向您发出请求,但仅在有新内容时才发送页面内容。您可以通过设置其他一些响应头来实现这一点:
ETag: <hash of the contents>
Last-Modified: <absolute date of last contents change>
当浏览器再次调用您的脚本时,它们将依次添加以下请求头:If-None-Match: <hash of the contents that you sent last time>
If-Modified-Since: <absolute date of last contents change>
ETag
主要用于减少网络流量,因为在某些情况下,为了知道内容的哈希值,您首先必须计算它。
如果您有本地文件缓存(文件有修改日期),则最容易应用Last-Modified
。一个简单的条件就可以使其工作:
if (!file_exists('cache.txt') ||
filemtime('cache.txt') > strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
// update cache file and send back contents as usual (+ cache headers)
} else {
header('HTTP/1.0 304 Not modified');
}
如果你无法使用文件缓存,你仍然可以使用ETag
来确定内容是否在此期间发生了更改。
If-None-Match
是一个请求头,而不是响应头,哈哈; 你应该在响应中设置 ETag: value
:) - Ja͢ck