缓存由 PHP 动态创建的 HTTP 响应
我认为我的问题似乎很随意,但请耐心等待,因为它变得有趣(至少对我而言:)).
I think my question seems pretty casual but bear with me as it gets interesting (at least for me :)).
考虑一个 PHP 页面,它的目的是从文件系统读取请求的文件并将其作为响应回显.现在的问题是如何为这个页面启用缓存?需要指出的是,文件可能非常庞大,启用缓存是为了避免客户端一次又一次地下载相同的内容.
Consider a PHP page that its purpose is to read a requested file from filesystem and echo it as the response. Now the question is how to enable cache for this page? The thing to point out is that the files can be pretty huge and enabling the cache is to save the client from downloading the same content again and again.
理想的策略是使用If-None-Match"请求头和ETag"响应头来实现反向代理缓存系统.尽管我知道这么多,但我不确定这是否可行,或者我应该返回什么作为响应才能实现这种技术!
The ideal strategy would be using the "If-None-Match" request header and "ETag" response header in order to implement a reverse proxy cache system. Even though I know this far, I'm not sure if this is possible or what should I return as response in order to implement this technique!
推荐答案
使用 PHP 处理大量或许多辅助文件并不是它的真正目的.
Serving huge or many auxiliary files with PHP is not exactly what it's made for.
相反,对于 nginx,请查看 X-accel,X-Sendfile 用于 Lighttpd 或 mod_xsendfile 用于 Apache.
Instead, look at X-accel for nginx, X-Sendfile for Lighttpd or mod_xsendfile for Apache.
初始请求由 PHP 处理,但一旦确定下载文件,它会设置一些标头以指示服务器应处理文件发送,之后 PHP 进程将被释放以提供其他服务.
The initial request gets handled by PHP, but once the download file has been determined it sets a few headers to indicate that the server should handle the file sending, after which the PHP process is freed up to serve something else.
然后您可以使用 Web 服务器为您配置缓存.
You can then use the web server to configure the caching for you.
静态生成的内容
如果您的内容是由 PHP 生成的并且创建起来特别昂贵,您可以将输出写入本地文件并再次应用上述方法.
If your content is generated from PHP and particularly expensive to create, you could write the output to a local file and apply the above method again.
如果您不能写入本地文件或不想写入,您可以使用 HTTP 响应头来控制缓存:
If you can't write to a local file or don't want to, you can use HTTP response headers to control caching:
Expires: <absolute date in the future>
Cache-Control: public, max-age=<relative time in seconds since request>
这将导致客户端缓存页面内容,直到它过期或用户强制重新加载页面(例如按 F5).
This will cause clients to cache the page contents until it expires or when a user forces a page reload (e.g. press F5).
动态生成的内容
对于动态内容,您希望浏览器每次都 ping 您,但仅在有新内容时才发送页面内容.您可以通过设置一些其他响应标头来实现此目的:
For dynamic content you want the browser to ping you every time, but only send the page contents if there's something new. You can accomplish this by setting a few other response headers:
ETag: <hash of the contents>
Last-Modified: <absolute date of last contents change>
当浏览器再次ping你的脚本时,它们会分别添加以下请求头:
When the browser pings your script again, they will add the following request headers respectively:
If-None-Match: <hash of the contents that you sent last time>
If-Modified-Since: <absolute date of last contents change>
ETag
主要用于减少网络流量,因为在某些情况下,要知道内容哈希,您首先必须计算它.
The ETag
is mostly used to reduce network traffic as in some cases, to know the contents hash, you first have to calculate it.
如果您有本地文件缓存(文件有修改日期),Last-Modified
是最容易应用的.一个简单的条件使它起作用:
The Last-Modified
is the easiest to apply if you have local file caches (files have a modification date). A simple condition makes it work:
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 you can't do file caches, you can still use ETag
to determine whether the contents have changed meanwhile.
相关文章