本文目录导读:

在 PHP 中实现“边缘缓存”,通常指的是利用 CDN、反向代理(如 Nginx、Varnish) 或 应用层缓存 将内容缓存在离用户更近的节点上,从而加速页面加载并减轻源服务器压力。
以下是几种在 PHP 中配合边缘缓存的典型实现方式:
配合 CDN 做边缘缓存
这是最标准的“边缘缓存”,你需要在 PHP 中正确设置 HTTP 缓存头,让 CDN 节点知道何时缓存、缓存多久。
// 缓存1小时,允许CDN/浏览器缓存
$expires = 3600;
header("Cache-Control: public, max-age={$expires}");
header("Expires: " . gmdate('D, d M Y H:i:s', time() + $expires) . " GMT");
// 输出页面内容
echo "这是被缓存的内容...";
关键点:
Cache-Control: public表示允许 CDN 和浏览器缓存。max-age指定缓存有效时间(秒),因用户而异(如登录态),需要设置private或no-cache,或使用 Cookie 校验。
高级用法:基于缓存标签(Surrogate-Key)
某些 CDN(如 Fastly、Cloudflare)支持通过 HTTP 头标记缓存标签,方便批量清除:
header("Surrogate-Key: blog-post:123 category:news");
// 后续可通过CDN API 删除包含该标签的所有缓存
与 Nginx 反向代理结合(FastCGI Cache)
Nginx 作为反向代理,可以缓存 PHP 输出的静态化页面,PHP 无需修改代码,但可以通过控制响应头来决定是否缓存。
Nginx 配置示例:
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=mycache:10m;
server {
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 启用缓存
fastcgi_cache mycache;
fastcgi_cache_valid 200 60m; # 成功响应缓存60分钟
fastcgi_cache_use_stale error timeout updating;
# 根据PHP自定义头决定是否绕过缓存
fastcgi_no_cache $skip_cache;
fastcgi_cache_bypass $skip_cache;
}
}
PHP 中动态控制:
// 如果用户已登录,禁止Nginx缓存
if ($logged_in) {
header("X-Accel-Expires: 0"); // 立即过期Nginx缓存
header("Cache-Control: no-cache, private");
} else {
header("X-Accel-Expires: 3600"); // 强制Nginx缓存1小时
header("Cache-Control: public, max-age=3600");
}
PHP 应用层边缘缓存(静态化 + 预热)
如果无法修改服务器配置,可以在 PHP 内部实现“伪边缘缓存”:将渲染好的 HTML 写入文件,再由 CDN 或 Nginx 作为静态文件提供。
示例:文件缓存 + 主动刷新
$cacheFile = __DIR__ . '/cache/page_' . md5($_SERVER['REQUEST_URI']) . '.html';
$cacheTime = 3600; // 1小时
// 检查缓存是否存在且未过期
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
readfile($cacheFile);
exit;
}
// 正常生成页面
ob_start();
echo "动态生成的内容...";
$content = ob_get_flush();
// 写入缓存文件
file_put_contents($cacheFile, $content);
适用于: 无CDN、低成本服务器,且内容变化不频繁的站点。
使用 Varnish 作为专用缓存层
Varnish 位于 PHP 与用户之间,专门处理 HTTP 缓存,PHP 通过设置 Cache-Control 和 Surrogate-Control 头控制 Varnish 行为。
PHP 示例(设置 TTL 和缓存分组):
header("Cache-Control: public, max-age=600, s-maxage=300");
// s-maxage 是共享缓存(如Varnish/CDN)专用的最大存活时间
header("Surrogate-Control: content=\"text/html\", max-age=3600");
Varnish VCL 可据此决定缓存策略:
sub vcl_recv {
if (req.http.Authorization || req.http.Cookie) {
return (pass); // 带Cookie/认证的不缓存
}
}
sub vcl_backend_response {
if (beresp.http.Surrogate-Control) {
# 可提取Surrogate-Control中的指令
}
}
边缘缓存的最佳实践总结
| 场景 | 推荐方式 | 注意事项 |
|---|---|---|
| 静态页面(文章、首页) | CDN + Cache-Control: public, max-age=3600 |
配合缓存标签快速失效 |
| 用户相关页面(购物车) | 不缓存,或使用Cache-Control: private |
或使用 ESI (Edge Side Includes) 部分缓存 |
| 频繁更新 | Nginx FastCGI Cache + 主动刷新API | 通过 X-Accel-Expires 头精细控制 |
| 离线完全静态化 | PHP 文件缓存 + CDN 静态资源服务 | 需考虑缓存失效机制(如CMS的自动刷新) |
| 使用专用缓存层 | Varnish + Surrogate-Key | 对于高流量站点性能极佳,但运维成本较高 |
关键注意点
- 避免缓存动态内容:登录态、购物车、CSRF Token 等页面必须设置
no-cache或private。 - 缓存失效策略:建议使用 基于标签的失效(如 Surrogate-Key),而不要用 URL 模式清除(效率低)。
- 混合模式:可以用 ESI(Edge Side Includes)技术,将页面中动态部分(如用户昵称)单独请求,其余部分缓存,PHP 可通过
esi:include占位符实现。 - 测试:使用
curl -I查看响应头中的Cache-Control、Age和X-Cache确认缓存是否生效。
如果你能给出具体场景(如 WordPress 站点、API 接口、会员系统等),我可以提供更针对性的缓存方案。