3

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

背景,SSCCE

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

### 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>

清漆 VCL 配置:

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/footer.php从缓存中加载,每 10/20 秒清除一次,同时navigation.php直接从后端服务器加载。当然,必须设置第一个index.php不能作为标头缓存的请求,但是可以从一开始就从缓存中加载。Set-Cookiefooter.php


我怎么能做到这一点?我知道CookieHTTP 请求中存在标头会导致缓存未命中,但我不能简单地删除它。

4

1 回答 1

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

于 2013-08-05T12:42:36.993 回答