You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Cache Control头配置Varnish 4+缓存(忽略Cookie)问题排查

Varnish缓存配置问题排查与解决方案

现有配置的核心问题

  • 未遵循后端Cache-Control头的public/max-age规则,全局强制设置TTL并清空Cache-Control,完全偏离需求
  • 遇到no-cache/no-store时,仅删除自定义头但未标记响应不可缓存,无法实现绕过缓存的要求
  • 全局强制删除Cookie相关头,忽略了需求中仅在public/max-age场景下才忽略Cookie缓存的规则
  • X-Force-Cache的重启逻辑可能引发请求循环,且与基于Cache-Control的核心规则冲突
  • 未实现缓存命中时隐藏Cache-Control头的额外需求

修正后的VCL配置

vcl 4.1;

sub vcl_recv {
    # 处理Authorization头,默认不缓存带授权信息的请求
    if (req.http.Authorization) {
        return (pass);
    }

    # POST请求直接绕过缓存
    if (req.method == "POST") {
        return (pass);
    }

    # X-Force-Cache强制缓存逻辑(保留原有需求,但不干扰核心Cache-Control规则)
    if (req.http.X-Force-Cache) {
        unset req.http.Cookie;
        unset req.http.Cache-Control;
        unset req.http.Pragma;
    }
}

sub vcl_hash {
    # 保留X-Force-Cache的哈希逻辑
    if (req.http.X-Force-Cache) {
        hash_data(req.http.X-Force-Cache);
    }
}

sub vcl_backend_response {
    # 场景1:后端返回no-cache/no-store,绕过缓存并保留Cookie
    if (beresp.http.Cache-Control ~ "(no-cache|no-store)") {
        set beresp.uncacheable = true;
        set beresp.ttl = 0s;
        return (deliver);
    }

    # 场景2:后端返回public或max-age,忽略Cookie并缓存
    if (beresp.http.Cache-Control ~ "(public|max-age=[0-9]+)") {
        unset beresp.http.Set-Cookie;
        unset bereq.http.Cookie;
        # 优先使用后端max-age值,若需要强制覆盖可取消下面注释
        # set beresp.ttl = std.duration(std.regex(beresp.http.Cache-Control, "max-age=([0-9]+)", 1) + "s", 7d);
    }

    # X-Force-Cache强制缓存逻辑,优先级低于Cache-Control规则
    if (bereq.http.X-Force-Cache) {
        unset beresp.http.Set-Cookie;
        unset bereq.http.Cookie;
        set beresp.ttl = 7d;
        unset beresp.http.Cache-Control;
        unset bereq.http.X-Force-Cache;
    }

    # 其他未匹配场景:默认不缓存(避免误缓存私有内容)
    else {
        set beresp.uncacheable = true;
        set beresp.ttl = 0s;
    }
}

sub vcl_deliver {
    # 缓存命中时隐藏Cache-Control头
    if (obj.hits > 0) {
        unset resp.http.Cache-Control;
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }

    set resp.http.X-Cache-Hits = obj.hits;
    set resp.http.Mobile = req.http.CloudFront-Is-Mobile-Viewer;
    set resp.http.X-Device = req.http.X-Device;

    # 移除可能引发循环的重启逻辑,X-Force-Cache头按需返回
    if (req.http.X-Force-Cache) {
        set resp.http.X-Force-Cache = req.http.X-Force-Cache;
    } else {
        unset resp.http.X-Force-Cache;
    }
}

关键调整说明

  • 核心规则对齐需求:严格按照后端Cache-Control头分支处理:
    • 匹配no-cache/no-store时,标记响应不可缓存并设置TTL为0,保留所有Cookie相关头以维持会话
    • 匹配public/max-age时,删除Cookie相关头实现缓存,优先使用后端返回的max-age值(如需强制覆盖可调整TTL)
  • 缓存命中隐藏头:在vcl_deliver中判断obj.hits > 0(缓存命中)时,直接删除resp.http.Cache-Control
  • 移除危险逻辑:删除vcl_deliver中的return(restart),避免请求循环
  • 默认安全策略:未匹配任何规则的场景默认标记为不可缓存,防止误缓存私有内容
  • 兼容原有强制缓存:X-Force-Cache逻辑保留,但优先级低于核心Cache-Control规则

内容的提问来源于stack exchange,提问作者Abhishek Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:26:27