【问题标题】:Why the beresp.ttl is set to 0 when a Cookie is added to the request in Varnish?为什么在 Varnish 的请求中添加 Cookie 时 beresp.ttl 设置为 0?
【发布时间】:2012-12-14 11:06:24
【问题描述】:

好的,所以我正在尝试让 Varnish 正常工作,但我有一个无法解释的奇怪行为(可能是由于缺乏理解)。

这是我想要做的:

GET http://scm.dev:6081/articles
If-None-Match: "50a0794aaca51fce202e86da428b7dca9b4bbff93"

我得到:

HTTP/1.1 200 OK
Age: 3                                    // Correctly using a cached result
Content-Length: 3878
Content-Type: application/json
Date: Fri, 14 Dec 2012 10:59:34 GMT
Via: 1.1 varnish
X-Cacheable: YES                          // It is correct
Cache-Control: max-age=10, public, s-maxage=20
Etag: "50a0794aca51fce202e86da428b7dca9b4bbff93"
Vary: Accept,Accept-Encoding

现在,如果我在请求中添加 Cookie:

GET http://scm.dev:6081/articles
If-None-Match: "50a0794aaca51fce202e86da428b7dca9b4bbff93"
Cookie: foo=bar

我得到一个非缓存响应和一个不可缓存的警告:

HTTP/1.1 200 OK
Age: 0                                    // Always set to 0
Content-Length: 3878
Content-Type: application/json
Date: Fri, 14 Dec 2012 10:59:34 GMT
Via: 1.1 varnish
X-Cacheable: NO:Not Cacheable             // It is not correct
Cache-Control: max-age=10, public, s-maxage=20
Etag: "50a0794aca51fce202e86da428b7dca9b4bbff93"
Vary: Accept,Accept-Encoding

如果检查后面的vcl配置,如果beresp.ttl小于等于0,则设置X-Cacheable: NO:Not Cacheable标头。

为什么?

我还假设返回 Cache-Control: public 的带有 Cookie 的请求应该被缓存,只要后端承担正确设置 public 参数的责任。

我会假设 X-Cacheable: NO:Got Session 会在使用 Cookie 发出请求时设置,但它甚至没有更进一步。

启动varnish daemon的命令行:

/usr/sbin/varnishd -P /var/run/varnishd.pid -a :6081 -T 192.168.1.100:6082 -f /etc/varnish/custom.vcl -S /etc/varnish/secret -s malloc,256m

这是我的custom.vcl

backend scm {
.host = "scm.dev";
.port = "80";
}

sub vcl_recv {
    set req.http.Surrogate-Capability = "abc=ESI/1.0";
}

sub vcl_fetch {
    if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
        unset beresp.http.Surrogate-Control;
        set beresp.do_esi = true;
    }

    # Varnish determined the object was not cacheable
    if (beresp.ttl <= 0s) {
        set beresp.http.X-Cacheable = "NO:Not Cacheable";

    # You don't wish to cache content for logged in users
    } elsif (req.http.Cookie ~ "(foo)") {
        set beresp.http.X-Cacheable = "NO:Got Session";

        return(hit_for_pass);
    # You are respecting the Cache-Control=private header from the backend
    } elsif (beresp.http.Cache-Control ~ "private") {
        set beresp.http.X-Cacheable = "NO:Cache-Control=private";

        return(hit_for_pass);
    # Varnish determined the object was cacheable
    } else {
        set beresp.http.X-Cacheable = "YES";
    }

    return(deliver);
}

sub vcl_hit {
    if (req.request == "PURGE") {
        set obj.ttl = 0s;
        error 200 "Purged";
    }
}

sub vcl_miss {
    if (req.request == "PURGE") {
        error 404 "Not purged";
    }
}

【问题讨论】:

    标签: varnish http-caching varnish-vcl


    【解决方案1】:

    by design,如果存在 cookie,Varnish 不会从缓存中获取任何请求。通常 cookie 表明响应对于特定用户是唯一的。

    如果您不关心 cookie,或者如果您想保留特定的 cookie,您可以完全在 vcl_recv() 中使用 unset req.http.Cookie;

    if(req.http.Cookie) {
      if (req.http.Cookie !~ "(important_cookie|php_session)" ) {
        remove req.http.Cookie;
      }
    }
    

    【讨论】:

    • 正如我在问题中所说,我假设带有 Cookie 但返回带有 Cache-Control: public 的响应的请求应该由 Varnish 缓存。听起来不对吗?如果是,并且如果我理解正确,我必须自己实现这种行为,对吗?
    • 很遗憾没有。 Varnish 只查看请求标头并根据它们做出传递请求的决定。 IE。它不会首先查找缓存副本和标题,而是绕过缓存。总是。如果您知道可以安全地缓存具有某些标头的内容,则可以将 cookie 添加到哈希中。 varnish-cache.org/trac/wiki/VCLExampleCacheCookies
    猜你喜欢
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    相关资源
    最近更新 更多