我在设置Varnish以正确处理ESI包含的子请求的会话cookie时遇到了问题。
三个文件:index.php
,navigation.php
和footer.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
标头会导致缓存未命中,但我不能简单地将其删除。
答案 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