如何指示 Varnish 根据响应 header 进行缓存?
How do I instruct Varnish to cache based on response header?
我在整个站点的各种 URL 上有一系列视频。我想用 Varnish 缓存它们,即使用户已登录。我可以使用 VCL 配置将某些 URL 列入白名单以进行缓存。但是我不知道如何将所有视频列入白名单。
有没有办法说 return 内容类型为 video/mp4 的所有响应都被缓存了?
决定从缓存中提供 object 和决定在缓存中存储 object 在 Varnish 中是两件不同的事情。这两种情况都需要考虑。
Built-in VCL
为了了解发生了什么 out-of-the-box,您需要查看以下 VCL 文件:https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin.vcl
这是执行的built-in VCL。对于每个子例程,当您没有在 VCL 文件中为相应的子例程执行显式 return(xyz)
时,将执行此逻辑。
这意味着您有某种安全网来保护您。
从技术角度来看,在将 VCL 文件编译成 C 代码之前,Varnish 编译器会将 built-in VCL 部分添加到您在 VCL 中扩展的子例程中。
我们从 built-in VCL
中学到了什么
built-in VCL 在可缓存性方面告诉我们以下内容:
- Varnish 只会从缓存中为
GET
和 HEAD
请求提供 object (参见 vcl_recv
)
- 如果
Cookie
或 Authorization
header 存在 (参见 vcl_recv
),Varnish 将不会从缓存中提供 object
- 如果
Set-Cookie
header 存在,Varnish 将不会在缓存中存储 object (参见 vcl_backend_response
)
- 如果 TTL 为零或更小,Varnish 将不会在缓存中存储 object (参见
vcl_backend_response
)
- 如果
Cache-Control
header 包含 no-store
(参见 vcl_backend_response
)[=,Varnish 将不会在缓存中存储 object 132=]
- 如果
Surrogate-Control
header 包含 no-cache
、no-store
或 private
[=114,Varnish 将不会在缓存中存储 object =](参见 vcl_backend_response
)
- 如果
Vary
header 通过 *
[=114] 对所有 header 执行缓存变化,Varnish 将不会在缓存中存储 object =](参见 vcl_backend_response
)
如何确保从缓存中提供视频文件
在 vcl_recv
中,您必须确保 Varnish 愿意从缓存中查找视频请求。实际上,这意味着照顾好 cookie。
我的建议是删除所有 cookie,除了您真正需要的那些。下面的示例将删除所有 cookie,但我的后端需要的 PHPSESSID
cookie 除外:
vcl 4.1;
sub vcl_recv {
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; =");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
}
此示例将从请求中删除跟踪 cookie,这很好,因为它们由 Javascript 处理。
当 PHPSESSID
cookie 未设置时,vcl_recv
将退回到 built-in VCL,请求将被处理来自缓存。
但在您的情况下,您希望从缓存中提供它们,即使用户已登录也是如此。这很好,因为视频是不受状态影响的静态文件。
问题是在请求上下文中您不能指定 Content-Type
信息。您必须使用 URL.
示例如下:
sub vcl_recv {
if(req.url ~ "^/video") {
return(hash);
}
}
此代码段将绕过 built-in VCL,如果 URL 与^/video
正则表达式模式。
如何确保视频文件存储在缓存中
当您在 vcl_recv
中执行显式 return(hash)
时,将创建散列并进行缓存查找。但是如果 object 没有存储在缓存中,你仍然会错过,这会导致后端请求。
当后端响应返回时,需要在缓存中保存一定时间。给定 built-in VCL,您必须确保没有指定 zero-TTL,并且 Cache-Control
响应 header 必须return 可缓存语法。
这就是我设置 Cache-Control
header 的方式,例如,如果我们想要缓存一天的视频文件:
Cache-Control: public, max-age=86400
Varnish 会遵守此 header,并会根据 max-age
语法将 TTL 设置为 1 天。
即使你不指定 Cache-Control
header,Varnish 仍会将其存储在缓存中,但为 2 分钟,这是默认的 TTL。
这是一个 Varnish 不会将 object 存储在缓存中的示例,基于 Cache-Control
header:
Cache-Control: private, max-age=0, s-maxage=0 ,no-cache, no-store
如果这些表达式中的任何一个在 Cache-Control
中,Varnish 将使 object 不可缓存。
如果 Set-Cookie
header 是响应的一部分,object 也变得不可缓存。
如果您不能完全控制后端服务器 return 编辑的 header,您仍然可以在 VCL 中靠运气。
这是一个 VCL 片段,我们强制将 objects 存储在图像和视频的缓存中:
sub vcl_backend_response {
if(beresp.http.Content-Type ~ "^(image|video)/") {
set beresp.ttl = 1d;
unset beresp.http.set-cookie;
return (deliver);
}
}
此示例将剥离 Set-Cookie
headers,将 TTL 覆盖为一天,并将显式存储和传送 object。只有当 Content-Type
响应 header 以 image/
或 video/
开头时才会出现这种情况
我在整个站点的各种 URL 上有一系列视频。我想用 Varnish 缓存它们,即使用户已登录。我可以使用 VCL 配置将某些 URL 列入白名单以进行缓存。但是我不知道如何将所有视频列入白名单。
有没有办法说 return 内容类型为 video/mp4 的所有响应都被缓存了?
决定从缓存中提供 object 和决定在缓存中存储 object 在 Varnish 中是两件不同的事情。这两种情况都需要考虑。
Built-in VCL
为了了解发生了什么 out-of-the-box,您需要查看以下 VCL 文件:https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin.vcl
这是执行的built-in VCL。对于每个子例程,当您没有在 VCL 文件中为相应的子例程执行显式 return(xyz)
时,将执行此逻辑。
这意味着您有某种安全网来保护您。
从技术角度来看,在将 VCL 文件编译成 C 代码之前,Varnish 编译器会将 built-in VCL 部分添加到您在 VCL 中扩展的子例程中。
我们从 built-in VCL
中学到了什么built-in VCL 在可缓存性方面告诉我们以下内容:
- Varnish 只会从缓存中为
GET
和HEAD
请求提供 object (参见vcl_recv
) - 如果
Cookie
或Authorization
header 存在 (参见vcl_recv
),Varnish 将不会从缓存中提供 object - 如果
Set-Cookie
header 存在,Varnish 将不会在缓存中存储 object (参见vcl_backend_response
) - 如果 TTL 为零或更小,Varnish 将不会在缓存中存储 object (参见
vcl_backend_response
) - 如果
Cache-Control
header 包含no-store
(参见vcl_backend_response
)[=,Varnish 将不会在缓存中存储 object 132=] - 如果
Surrogate-Control
header 包含no-cache
、no-store
或private
[=114,Varnish 将不会在缓存中存储 object =](参见vcl_backend_response
) - 如果
Vary
header 通过*
[=114] 对所有 header 执行缓存变化,Varnish 将不会在缓存中存储 object =](参见vcl_backend_response
)
如何确保从缓存中提供视频文件
在 vcl_recv
中,您必须确保 Varnish 愿意从缓存中查找视频请求。实际上,这意味着照顾好 cookie。
我的建议是删除所有 cookie,除了您真正需要的那些。下面的示例将删除所有 cookie,但我的后端需要的 PHPSESSID
cookie 除外:
vcl 4.1;
sub vcl_recv {
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; =");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
}
此示例将从请求中删除跟踪 cookie,这很好,因为它们由 Javascript 处理。
当 PHPSESSID
cookie 未设置时,vcl_recv
将退回到 built-in VCL,请求将被处理来自缓存。
但在您的情况下,您希望从缓存中提供它们,即使用户已登录也是如此。这很好,因为视频是不受状态影响的静态文件。
问题是在请求上下文中您不能指定 Content-Type
信息。您必须使用 URL.
示例如下:
sub vcl_recv {
if(req.url ~ "^/video") {
return(hash);
}
}
此代码段将绕过 built-in VCL,如果 URL 与^/video
正则表达式模式。
如何确保视频文件存储在缓存中
当您在 vcl_recv
中执行显式 return(hash)
时,将创建散列并进行缓存查找。但是如果 object 没有存储在缓存中,你仍然会错过,这会导致后端请求。
当后端响应返回时,需要在缓存中保存一定时间。给定 built-in VCL,您必须确保没有指定 zero-TTL,并且 Cache-Control
响应 header 必须return 可缓存语法。
这就是我设置 Cache-Control
header 的方式,例如,如果我们想要缓存一天的视频文件:
Cache-Control: public, max-age=86400
Varnish 会遵守此 header,并会根据 max-age
语法将 TTL 设置为 1 天。
即使你不指定 Cache-Control
header,Varnish 仍会将其存储在缓存中,但为 2 分钟,这是默认的 TTL。
这是一个 Varnish 不会将 object 存储在缓存中的示例,基于 Cache-Control
header:
Cache-Control: private, max-age=0, s-maxage=0 ,no-cache, no-store
如果这些表达式中的任何一个在 Cache-Control
中,Varnish 将使 object 不可缓存。
如果 Set-Cookie
header 是响应的一部分,object 也变得不可缓存。
如果您不能完全控制后端服务器 return 编辑的 header,您仍然可以在 VCL 中靠运气。
这是一个 VCL 片段,我们强制将 objects 存储在图像和视频的缓存中:
sub vcl_backend_response {
if(beresp.http.Content-Type ~ "^(image|video)/") {
set beresp.ttl = 1d;
unset beresp.http.set-cookie;
return (deliver);
}
}
此示例将剥离 Set-Cookie
headers,将 TTL 覆盖为一天,并将显式存储和传送 object。只有当 Content-Type
响应 header 以 image/
或 video/