我有一个电子商务应用程序,我尝试设置用于缓存 - 最初通过Symfony2反向代理,但最终通过生产中的Varnish。我在Apache2上使用Symfony 2.1.8。
我的问题是,当主控制器操作被缓存时,我无法为每个请求重新检查ESI标签(对于私人内容如篮子内容很重要),但我不明白为什么。
例如,我使用以下代码缓存主页:
public function indexAction(Request $request)
{
// check cache
$homepage = $this->getHomepage();
$response = new Response();
$response->setPublic();
$etag = md5('homepage'.$homepage->getUpdated()->getTimestamp());
$response->setETag($etag);
$response->setLastModified($homepage->getUpdated());
if ($response->isNotModified($request))
{
// use cached version
return $response;
}
else
{
return $this->render(
'StoreBundle:Store:index.html.twig',
array(
'page' => $homepage
),
$response
);
}
}
渲染模板扩展了基本布局模板,其中包含以下ESI以显示篮子:
{% render 'PurchaseBundle:Basket:summary' with {}, { 'standalone': true } %}
(编辑:在阅读迭戈的回答后,我也使用了推荐的语法:
{% render url('basket_summary') with {}, {'standalone': true} %}
不幸的是,这没有任何区别。)
我一直在玩篮子摘要的代码,但这就是我目前所拥有的。
public function summaryAction()
{
$response = new Response();
$response->setPrivate();
$response->setVary(array('Accept-Encoding', 'Cookie'));
if ($this->basket->getId())
{
$etag = md5($this->getUniqueEtag());
$response->setLastModified($this->basket->getUpdated());
}
else
{
$etag = md5('basket_summary_empty');
}
$response->setETag($etag);
if ($response->isNotModified($this->request))
{
// use cached version
return $response;
}
else
{
return $this->render(
'PurchaseBundle:Basket:summary.html.twig',
array(
'basket' => $this->basket
),
$response
);
}
}
在主页以外的页面上(尚未缓存),篮子摘要缓存工作正常,它始终显示正确的数据。只有当您返回主页时,您才会看到过时的信息。记录确认,除非summaryAction
实际呈现,否则不会在主页上调用indexAction
。
在每个页面请求后使用error_log($kernel->getLog())
我得到一个非缓存页面:
GET /categories/collections: miss; GET /_internal/secure/PurchaseBundle:Basket:summary/none.html: stale, valid, store; GET /_internal/secure/CatalogBundle:Search:form/none.html: miss; GET /esi/menu/main: fresh
这适用于缓存的主页:
GET /: fresh
我必须遗漏一些明显的东西,但文档似乎没有涵盖这一点,但它暗示它只是ESI应该用于的那种东西。
答案 0 :(得分:3)
自2.0.20 / 2.1.5以来,根据CVE-2012-6431,Symfony2采用完全限定的URL而不是控制器逻辑路径。所以,而不是你当前的ESI:
{% render 'PurchaseBundle:Basket:summary' with {}, { 'standalone': true } %}
你应该创建一个路由,然后在树枝上使用url方法:
{% render url('basket_summary') with {}, {'standalone': true} %}
另请注意,今天(3月1日)已发布一个新的稳定版Symfony(2.2.0)major improvements on sub-requests management。使用这个新版本,您可以采用两种方法(摘自本书中HTTP Cache章节的master version):
{# you can use a controller reference #}
{{ render_esi(controller('...:news', { 'max': 5 })) }}
{# ... or a URL #}
{{ render_esi(url('latest_news', { 'max': 5 })) }}
关于当前版本链接章节的附注也值得一读,因为它们包含了可以帮助您找到实际问题的美味信息和好的提示。
答案 1 :(得分:2)
Symfony2中的ESI似乎不适用于您使用的Latmodified / Etag缓存验证结构。见这里:https://groups.google.com/forum/?fromgroups=#!topic/symfony2/V4BItzpLbOs
这里有类似的问题: Edge Side Includes and validation cache in Symfony 2
我一直在尝试和你一样,但只能通过使用到期缓存来使ESI工作。