PHP 怎么PHP Varnish

wen PHP项目 1

本文目录导读:

PHP 怎么PHP Varnish

  1. Varnish基础配置
  2. VCL配置文件示例
  3. PHP代码配合Varnish
  4. 高级特性
  5. 集成框架缓存
  6. Varnish监控
  7. 最佳实践
  8. 常见问题解决

我来详细介绍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

最佳实践

  1. 精确控制缓存时间类型设置不同的TTL
  2. 处理动态内容:对登录用户、个性化内容不缓存
  3. 缓存策略:使用Cache-Control头与Varnish配合
  4. 监控和统计:关注缓存命中率,优化缓存策略
  5. 备份默认后端:配置多个后端服务器提高可用性
  6. 安全考虑:使用密钥保护清理操作
  7. 测试:在开发环境充分测试缓存配置

常见问题解决

# 检查Varnish是否运行
systemctl status varnish
# 查看日志
tail -f /var/log/varnish.log
# 检查端口监听
netstat -tulpn | grep 80
netstat -tulpn | grep 8080
# 清除所有缓存
varnishadm "ban req.url ~ /"

通过合理使用Varnish,可以显著提升PHP应用的性能和响应速度,特别适合高流量的内容型网站。

抱歉,评论功能暂时关闭!