我有一个电子商务应用程序,我正在尝试设置缓存 - 最初通过 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 } %}
(编辑:阅读 Diego 的回答后,我也使用了推荐的语法:
{% 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 应该用于的那种事情。