本文目录导读:

我来详细介绍PHP如何使用Varnish作为缓存层。
Varnish基础配置
安装Varnish
# Ubuntu/Debian sudo apt-get install varnish # CentOS/RHEL sudo yum install varnish
配置Varnish端口
# /etc/varnish/default.vcl
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080"; # PHP-FPM/Nginx端口
}
# 监听80端口
# /etc/varnish/varnish.params
VARNISH_LISTEN_PORT=80
VARNISH_LISTEN_ADDRESS=0.0.0.0
VCL配置文件示例
# /etc/varnish/default.vcl
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
# ACL允许清除缓存
acl purge {
"localhost";
"127.0.0.1";
}
sub vcl_recv {
# 只缓存GET和HEAD请求
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# 不缓存登录页面
if (req.url ~ "^/login" || req.url ~ "^/admin") {
return (pass);
}
# 设置模拟客户端IP
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
# 缓存GET请求
if (req.method == "GET") {
return (hash);
}
return (pass);
}
sub vcl_backend_response {
# 缓存后端响应
if (beresp.status == 200) {
# 根据URL设置不同的缓存时间
if (bereq.url ~ "^/products") {
set beresp.ttl = 1h;
} elseif (bereq.url ~ "^/blog") {
set beresp.ttl = 15m;
} else {
set beresp.ttl = 5m;
}
# 不缓存包含Set-Cookie的响应
if (beresp.http.Set-Cookie) {
set beresp.ttl = 0s;
return (deliver);
}
}
return (deliver);
}
sub vcl_deliver {
# 添加缓存状态头
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# 不显示缓存命中数给客户
# unset resp.http.X-Varnish;
}
sub vcl_purge {
return (synth(200, "Purged"));
}
PHP代码配合Varnish
设置缓存头
<?php
// 设置缓存头,让Varnish知道缓存策略
function set_cache_headers($ttl = 300) {
// 不缓存页面
header("Cache-Control: no-cache, no-store, must-revalidate");
// 如果用户已登录,不缓存
if (isset($_SESSION['user_id'])) {
header("Cache-Control: no-cache, no-store");
header("Pragma: no-cache");
return false;
}
// 设置缓存头
header("Cache-Control: public, max-age=" . $ttl);
header("Pragma: cache");
return true;
}
// 使用示例
if (set_cache_headers(600)) {
// 页面内容将被缓存
echo generate_dynamic_content();
} else {
// 动态内容,不缓存
echo generate_personalized_content();
}
?>
缓存清除(PURGE请求)
<?php
class VarnishCacheManager {
private $varnishHosts = ['127.0.0.1'];
private $varnishPort = 80;
public function purgeCache($url) {
foreach ($this->varnishHosts as $host) {
$this->sendPurgeRequest($host, $url);
}
}
private function sendPurgeRequest($host, $url) {
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://{$host}:{$this->varnishPort}" . $url,
CURLOPT_CUSTOMREQUEST => "PURGE",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Purge-Key: secret_key",
"Host: " . $_SERVER['HTTP_HOST']
]
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
return $httpCode == 200;
}
}
// 使用示例
$cacheManager = new VarnishCacheManager();
$cacheManager->purgeCache('/products');
?>
高级特性
使用BAN正则批量清理
sub vcl_recv {
if (req.method == "BAN") {
# 验证BAN密钥
if (req.http.Ban-Key != "your-secret-key") {
return (synth(403, "Forbidden"));
}
ban("req.url ~ " + req.http.Ban-Url);
return (synth(200, "Banned"));
}
}
// PHP批量清理
class VarnishBanner {
public function ban($pattern) {
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://127.0.0.1/",
CURLOPT_CUSTOMREQUEST => "BAN",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Ban-Key: your-secret-key",
"Ban-Url: " . $pattern
]
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
return $httpCode == 200;
}
}
// 清理所有商品页面缓存
$banner = new VarnishBanner();
$banner->ban("^/products/");
集成框架缓存
Laravel/Lumen
// 在中间件或控制器中
public function index(Request $request) {
// 设置缓存头
header('Cache-Control: public, max-age=300');
// 使用Varnish缓存
$cacheKey = 'products_page_' . $request->page;
return Cache::remember($cacheKey, 300, function () {
return Product::paginate(10);
});
}
// 缓存清理
public function update(Product $product) {
// 更新产品逻辑...
// 清除相关缓存
$this->purgeCache("/products/" . $product->id);
$this->purgeCache("/products");
}
Symfony框架
// 配置文件 config/packages/cache.yaml
framework:
cache:
app: cache.adapter.redis
// 控制器中使用
public function index(ProductRepository $products) {
$response = new JsonResponse($products->findAll());
$response->setPublic();
$response->setMaxAge(300);
return $response;
}
Varnish监控
# 查看缓存命中率 varnishstat # 实时监控 varnishlog # 查看缓存内容 varnishadm # 检查配置 varnishd -C -f /etc/varnish/default.vcl
最佳实践
- 精确控制缓存时间类型设置不同的TTL
- 处理动态内容:对登录用户、个性化内容不缓存
- 缓存策略:使用
Cache-Control头与Varnish配合 - 监控和统计:关注缓存命中率,优化缓存策略
- 备份默认后端:配置多个后端服务器提高可用性
- 安全考虑:使用密钥保护清理操作
- 测试:在开发环境充分测试缓存配置
常见问题解决
# 检查Varnish是否运行 systemctl status varnish # 查看日志 tail -f /var/log/varnish.log # 检查端口监听 netstat -tulpn | grep 80 netstat -tulpn | grep 8080 # 清除所有缓存 varnishadm "ban req.url ~ /"
通过合理使用Varnish,可以显著提升PHP应用的性能和响应速度,特别适合高流量的内容型网站。