【问题标题】:Make Varnish ignore requests with Cookie header使用 Cookie 标头使 Varnish 忽略请求
【发布时间】:2014-05-21 12:45:55
【问题描述】:

Varnish 默认行为是从不查找包含Cookie 标头的请求。换句话说,包含Cookie 标头的请求永远不会被缓存。我需要覆盖此行为以忽略带有 Cookie 标头的请求。

考虑我的应用程序中的下一个用户行为:

  1. 用户进入应用主页(/),页面应该被缓存,后端返回publiccache-control,一切正常,页面被Varnish缓存。
  2. 用户导航到不可缓存的自定义页面 (/not-cacheable),后端返回 private 缓存控制。还会在响应中返回 Set-Cookie 标头。 Varnish 会忽略这个请求,最终用户会得到一个 cookie。到目前为止一切顺利。
  3. 用户导航回主页 (/),请记住,该主页已被缓存。问题是,用户请求现在带有一个Cookie 标头。这会导致 Varnish 忽略请求并委托给后端。

删除Cookie 不起作用,因为当用户返回/not-cacheable 路由时,他将看不到他的个性化页面,因为Cookie 标头已被删除.相反,后端会返回一个新生成的会话,并在 Set-Cookie 中添加一个新的 id。

此外,在 Varnish 中查找每个 Cookie 请求会导致每个关于方法或后端响应的请求都被缓存。

如果有某种方法可以告诉 Varnish 忽略 Cookie 标头,这样我就可以缓存带有该标头的请求,让后端决定请求是否应该可缓存。

有什么想法吗?

【问题讨论】:

    标签: http cookies browser-cache varnish varnish-vcl


    【解决方案1】:

    我认为删除 vcl_recv 中的 cookie 标头应该可以解决问题,这是我在 wordpress 上使用的忽略前端但不忽略后端的内容,您可以轻松删除 if 条件以使其覆盖整个服务器

    sub vcl_recv {
      if (req.url !~ "^/wp-"){
        unset req.http.cookie;
      }
    }
    

    【讨论】:

    • 这个我已经试过了,但是效果是没有Cookie标头被传递到后端,因此后端就像是一个新请求并生成一个新会话。
    • 只有前端,后端才能正常运行
    • 您的应用是否也为前端生成 cookie?
    • 是的,因为我有一个特殊的视图,需要 cookie 才能记住用户设置。我的意思是,我需要一个 Varnish 的方法来 ignore cookie,表现得好像不存在,但将标头完好无损地传递给后端。unset 方法只是删除了header,当后端收到请求时,它就消失了。
    • 您可以尝试在 cookie 存在时返回 lookup,就像在第三个示例中一样 varnish-cache.org/trac/wiki/VCLExampleCacheCookies
    【解决方案2】:

    为了记录,我终于想出了一个VCL脚本,它使用自定义标头并重新启动请求来解决这个问题:

    backend default
    {
        .host = "127.0.0.1";
        .port = "8080";
    }
    
    sub vcl_recv
    {
        if(req.http.X-Force-Backend)
        {
            return(pass);
        }
    
        if(req.http.Cookie && req.request ~ "(GET|HEAD)")
        {
            set req.http.X-Cookie = req.http.Cookie;
            remove req.http.Cookie;
    
            return(lookup);
        }
    }
    
    sub vcl_deliver
    {
        if(resp.http.Cache-control ~ "(private|no-cache|no-store)" 
            && !req.http.X-Force-Backend
            && req.request ~ "(GET|HEAD)"
        )
        {
            set req.http.X-Force-Backend = "YES";
            set req.http.Cookie = req.http.X-Cookie;
    
            remove req.http.X-Cookie;
    
            return(restart);
        }
    }
    

    如您所见,通过始终删除Cookie 标头并在我们有来自后端的不可缓存响应时重新启动请求,我们可以达到预期的效果。我不知道可能的性能缺陷,但我在生产中使用它并且效果很好。

    我还写了一篇关于这个特定问题的博客文章,如果有人同时使用 Symfony 和 Varnish,可能会很有趣:http://albertofem.com/post/symfony-varnish-and-http-practical-considerations.html

    【讨论】:

    • 我已经用类似的方法实现了这一点,但是我没有在 vcl_deliver 中添加 cookie 并重新启动请求,而是在将 cookie 传递到后端之前将其添加回 vcl_miss 和 vcl_pass。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多