维护包含ESI的请求的会话

时间:2013-08-02 15:40:23

标签: caching http-headers varnish esi

我在设置Varnish以正确处理ESI包含的子请求的会话cookie时遇到了问题。

背景,SSCCE

三个文件:index.phpnavigation.phpfooter.php使用ESI组合在一起,其中前两个文件是有状态的,但只有index.php可缓存,而{{1}是完全无国籍的。

footer.php

Varnish VCL配置:

### index.php
<?php

session_start();

header('Cache-Control: public, s-maxage=10');
header('Surrogate-Control: content="ESI/1.0"');

?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />

        <title>Varnish test</title>
    </head>
    <body>
        <esi:include src="http://localhost/WWW/navigation.php" />
        <p>Primary content: <?php echo date('r') ?></p>
        <esi:include src="http://localhost/WWW/footer.php" />
    </body>
</html>

### footer.php
<?php

header('Cache-Control: public, s-maxage=20');

?>
<p>Footer: <?php echo date('r') ?></p>

### navigation.php
<?php

session_start();

if (!isset($_SESSION['counter'])) {
    $_SESSION['counter'] = 0;
}

$_SESSION['counter'] += 1;

header('Cache-Control: private');

?>
<p>Navigation: <?php echo $_SESSION['counter'] ?></p>

期望的结果

我希望从缓存中加载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; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } } / index.php,每10/20秒清除一次,而footer.php直接从后端服务器加载。当然,对navigation.php的第一个请求无法缓存,因为必须设置index.php标头,但是Set-Cookie可以从最开始从缓存加载。


我怎么能实现这一目标?我知道HTTP请求中存在footer.php标头会导致缓存未命中,但我不能简单地将其删除。

1 个答案:

答案 0 :(得分:1)

而不是答案而不是答案,而是长期适合一个。

上面的例子没有转义Varnish默认VCL [1],如果你不避免,Varnish总会将它的默认逻辑附加到你的VCL代码[2]。

在这种情况下,您至少需要:

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

Varnish也不会缓存任何响应,包括Set-Cookie标头,除非你强制它。

[1] https://www.varnish-cache.org/docs/3.0/reference/vcl.html#examples

[2] https://www.varnish-software.com/static/book/VCL_Basics.html#the-vcl-state-engine