如何使缓存标记与 FOSHttpCacheBundle 和 Varnish 一起工作?
How to make Cache Tagging work with FOSHttpCacheBundle and Varnish?
我配置了 Symfony 和 FOSHttpCacheBundle(遵循 FOSHttpCache documentation 中的 Varnish 配置说明)。
我向我的控制器添加了一个操作,它在响应 HTTP header:
中添加了一个 test
标记
<?php
use FOS\HttpCacheBundle\Configuration\Tag;
class MyController extends Controller
{
/**
* @Route("/test1", name="acme_my_test1")
* @Tag("test")
*/
public function test1Action()
{
return new Response(rand(0, 1000));
}
}
但是,每当我调用 /test1
URL 时,数字会发生变化,显示缓存未激活。
请注意,我的应用程序不使用任何 cookie,我可以测试 X-Cache-Tags
header 是否已发送到 Varnish(由于 vlc_deliver
指令,它在对浏览器的响应中将其剥离).
配置中有什么我会遗漏的吗? Varnish 和 Nginx 运行 在同一台服务器上。
这是我的 Symfony config.yml
文件中与 HTTP 缓存相关的配置:
framework:
trusted_hosts: ~
trusted_proxies: [127.0.0.1]
fos_http_cache:
proxy_client:
varnish:
servers: 127.0.0.1:80
base_url: mywebsite.localhost.com
tags:
enabled: true
和 /etc/varnish/default.vcl
中的 Varnish 配置:
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
acl invalidators {
"localhost";
}
sub vcl_recv {
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
} else {
set req.http.X-Forwarded-Port = "80";
}
set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.method == "PURGE") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
return (purge);
}
if (req.http.Cache-Control ~ "no-cache" && client.ip ~ invalidators) {
set req.hash_always_miss = true;
}
if (req.method == "BAN") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
if (req.http.X-Cache-Tags) {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
+ " && obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags
);
} else {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
);
}
return (synth(200, "Banned"));
}
}
sub vcl_backend_response {
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (!resp.http.X-Cache-Debug) {
unset resp.http.X-Url;
unset resp.http.X-Host;
unset resp.http.X-Cache-Tags;
}
}
好的,我找到了。
在我的配置中一切都很好,除了我必须添加一些过期时间 headers。我认为标签 header 就足够了,但还需要一些 long-time 过期 header。
动作必须如下所示:
<?php
use FOS\HttpCacheBundle\Configuration\Tag;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
class MyController extends Controller
{
/**
* @Route("/test1", name="acme_my_test1")
* @Tag("test")
* @Cache(expires="+1 year")
*/
public function test1Action()
{
return new Response(rand(0, 1000));
}
}
我对ESI标签和标签还有一点小问题,但这不在这个问题的范围内。
我配置了 Symfony 和 FOSHttpCacheBundle(遵循 FOSHttpCache documentation 中的 Varnish 配置说明)。
我向我的控制器添加了一个操作,它在响应 HTTP header:
中添加了一个test
标记
<?php
use FOS\HttpCacheBundle\Configuration\Tag;
class MyController extends Controller
{
/**
* @Route("/test1", name="acme_my_test1")
* @Tag("test")
*/
public function test1Action()
{
return new Response(rand(0, 1000));
}
}
但是,每当我调用 /test1
URL 时,数字会发生变化,显示缓存未激活。
请注意,我的应用程序不使用任何 cookie,我可以测试 X-Cache-Tags
header 是否已发送到 Varnish(由于 vlc_deliver
指令,它在对浏览器的响应中将其剥离).
配置中有什么我会遗漏的吗? Varnish 和 Nginx 运行 在同一台服务器上。
这是我的 Symfony config.yml
文件中与 HTTP 缓存相关的配置:
framework:
trusted_hosts: ~
trusted_proxies: [127.0.0.1]
fos_http_cache:
proxy_client:
varnish:
servers: 127.0.0.1:80
base_url: mywebsite.localhost.com
tags:
enabled: true
和 /etc/varnish/default.vcl
中的 Varnish 配置:
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
acl invalidators {
"localhost";
}
sub vcl_recv {
if (req.http.X-Forwarded-Proto == "https" ) {
set req.http.X-Forwarded-Port = "443";
} else {
set req.http.X-Forwarded-Port = "80";
}
set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.method == "PURGE") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
return (purge);
}
if (req.http.Cache-Control ~ "no-cache" && client.ip ~ invalidators) {
set req.hash_always_miss = true;
}
if (req.method == "BAN") {
if (!client.ip ~ invalidators) {
return (synth(405, "Not allowed"));
}
if (req.http.X-Cache-Tags) {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
+ " && obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags
);
} else {
ban("obj.http.X-Host ~ " + req.http.X-Host
+ " && obj.http.X-Url ~ " + req.http.X-Url
+ " && obj.http.content-type ~ " + req.http.X-Content-Type
);
}
return (synth(200, "Banned"));
}
}
sub vcl_backend_response {
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (!resp.http.X-Cache-Debug) {
unset resp.http.X-Url;
unset resp.http.X-Host;
unset resp.http.X-Cache-Tags;
}
}
好的,我找到了。 在我的配置中一切都很好,除了我必须添加一些过期时间 headers。我认为标签 header 就足够了,但还需要一些 long-time 过期 header。
动作必须如下所示:
<?php
use FOS\HttpCacheBundle\Configuration\Tag;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
class MyController extends Controller
{
/**
* @Route("/test1", name="acme_my_test1")
* @Tag("test")
* @Cache(expires="+1 year")
*/
public function test1Action()
{
return new Response(rand(0, 1000));
}
}
我对ESI标签和标签还有一点小问题,但这不在这个问题的范围内。