如何为 Symfony2 站点正确设置 Varnish?

Posted

技术标签:

【中文标题】如何为 Symfony2 站点正确设置 Varnish?【英文标题】:How to properly set up Varnish for Symfony2 sites? 【发布时间】:2012-02-14 07:05:24 【问题描述】:

我有一个使用 Symfony2 反向代理进行缓存的网站(带有 ESI)。平均响应时间约为 100 毫秒。我尝试在服务器上安装 Varnish 进行尝试。我一步一步跟着guide from Symfony cookbook,删除了cache文件夹中的所有内容,但是我尝试的时候还是创建了http_cache文件夹。所以我想我可以尝试从app.php 中注释掉$kernel = new AppCache($kernel);。那工作得很好。 http_cache 不再由 varnishstat 创建,Varnish 似乎在工作:

12951         0.00         0.08 cache_hitpass - Cache hits for pass
 1153         0.00         0.01 cache_miss - Cache misses

大约有 14000 个请求,所以我认为一切都会好起来的。但在回应之后,我发现响应提高到了大约 2 秒。

Apache 在端口 9000 上运行,Varnish 在 8080 上运行。所以我使用 echoping -n 10 -h http://servername/ X.X.X.X:8080 进行回应。

我不知道可能出了什么问题。使用 Varnish 和 Symfony2 是否需要任何其他设置?还是我只是做错了什么?


根据要求,这是我的default.vcl,到目前为止我已经进行了修改。

我发现 Varnish 的默认配置有 2 个问题:

它不会缓存带有 cookie 的请求(我的应用程序中的每个人都分配了会话) 它会忽略Cache-Control: no-cache 标头

所以我在我的配置中添加了这些情况的条件,它现在执行得相当好(从使用 S2 反向代理的 ~160 提高了 ~175 req/s - 但老实说,我期待更多)。我只是不知道如何检查它是否一切正常,所以欢迎任何输入。

大多数页面的缓存因 cookie 而异,s-maxage 1200。常见的 ESI 包含不因 cookie 而异,s-maxage 非常低(文章、文章列表)。用户个人资料页面根本没有被缓存(no-cache),我不确定 ESI 是否包含在这些页面上,甚至被 Varnish 缓存了。只有由 cookie 改变的 ESI 是带有用户特定信息的标题(在 100% 的页面上)。

这篇文章中的所有内容都是针对 Varnish 3.X 的(我个人使用的是 3.0.2)。

另外,经过几周的研究,我真的不知道我在做什么了,所以如果你在配置中发现一些奇怪的东西,请告诉我。

【问题讨论】:

5 美分,基于我最近的经验。这完全取决于 Vasnish 配置,尤其是您是否有足够的可用内存。请出示您的sub vcl_recvsub vcl_fetchbackend 用配置更新了原始帖子。我想到的另一件事是用户cookies(可能还有跟踪cookies)。我们页面上的每个请求都有它们。但我不明白为什么 varnishstat 说它会缓存 90% 的请求。当我们使用 Symfony2 反向代理时,我们从来没有遇到过问题。 我的设置中有类似的vcl_recv,虽然我也有这些行:set req.http.X-Forwarded-Port = "80"; set req.http.X-Forwarded-Proto = "http"; 【参考方案1】:

如果这是您的全部配置,则 vcl_recv 会配置两次。

在你要缓存的页面中,可以发送缓存头吗?这是最有意义的,因为图像可能已经有您的 apache 缓存标头,并且应用程序逻辑决定了可以实际缓存的页面,但您也可以在 varnish 中强制执行此操作。

您可以像这样使用 vcl_recv:

# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch 

    # set minimum timeouts to auto-discard stored objects
    # set beresp.prefetch = -30s;
    set beresp.grace = 120s;

    if (beresp.ttl < 48h) 
      set beresp.ttl = 48h;

    if (!beresp.cacheable) 
        pass;

    if (beresp.http.Set-Cookie) 
        pass;

    # if (beresp.http.Cache-Control ~ "(private|no-cache|no-store)") 
    # pass;

    if (req.http.Authorization && !beresp.http.Cache-Control ~ "public") 
        pass;


这个缓存,在清漆中,只缓存设置为可缓存的请求。另外,请注意您的配置不会缓存带有 cookie 的请求。

【讨论】:

是的,我认为整个问题都出在 cookie 上。我将在今天晚些时候更新这个问题,提供更多信息和进展。 啊废话,没注意到我发布了 2 次 recv 而不是 recv 和 fetch > 编辑了 OP,在该行下方添加了更多信息。 如果你想缓存包含cookies的请求,你可以尝试在你的vcl_recv中添加这样的东西:unset req.http.cookie;【参考方案2】:

我很惊讶这在 10 个月内没有得到真正完整的答案。这可能是一个非常有用的页面。

你自己指出:

Varnish 不缓存带有 cookie 的请求 Varnish 忽略 Cache-Control: no-cache header

首先,您应用中的每个人都需要会话吗?如果没有,请不要启动会话,或者至少延迟启动它,直到确实有必要(即他们登录或其他)。

如果您仍然可以在用户登录时缓存页面,那么您需要非常小心,不要为用户提供原本是为其他人提供的页面。但是,如果您要这样做,请编辑 vcl_recv() 以去除您要缓存的页面的会话 cookie。

您可以轻松让 Varnish 处理 vcl_fetch() 中的 no-cache 指令,实际上您已经完成了。

我发现的另一个问题是 Symfony 默认将 max-age 设置为 0,这意味着它们永远不会被 vcl_fetch 中的默认逻辑缓存

我还注意到您在 Varnish 中将端口设置为:

backend default 
    .host = "127.0.0.1";
    .port = "80";

您自己说过 Apache 在端口 9000 上运行,所以这似乎不匹配。您通常会将 Varnish 设置为侦听默认端口 (80),并将 Varnish 设置为在端口 9000 或其他端口上查找后端。

【讨论】:

以上是关于如何为 Symfony2 站点正确设置 Varnish?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Symfony 2 CLI 工具,如何为子类生成具有正确类型提示的 getter 和 setter?

Symfony 2. 如何为实体的嵌入表单设置默认值?

如何为站点框架 django 设置多个 settings.py?

Symfony2:如何为整个应用程序强制使用 HTTPS?

如何为用户“伪装”或“重命名”页面名称/位置/ URL,但仍允许外部站点通过HTTP_REFERER正确读取真实的URL

如何为我的 symfony2 网站实现权限角色/组系统