我有一系列关于网站上各种URL的视频。我想用Varnish缓存它们,,即使用户登录。我可以使用VCL配置来将某些URL列入白名单进行缓存。但我不知道如何将所有视频列入白名单。
有没有一种方法可以说,所有返回的内容类型为video/mp4的响应都被缓存了?
在Varnish中,决定从缓存中提供对象和决定将对象存储在缓存中是两件不同的事情。这两种情况都需要考虑在内。
内置VCL
为了了解开箱即用的情况,您需要查看以下VCL文件:https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin.vcl
这是执行的内置VCL。对于每个子例程,当您没有在VCL文件中为相应的子例程执行显式return(xyz)
时,就会执行此逻辑。
这意味着你有某种安全网来保护你。
从技术角度来看,在将VCL文件编译成C代码之前,Varnish编译器会将内置的VCL部分添加到您在VCL中扩展的子例程中。
我们从内置的VCL中学到了什么
当谈到可缓存性时,内置的VCL教会了我们以下几点:
- Varnish将仅为
GET
和HEAD
请求的缓存中的对象提供(请参阅vcl_recv
) - 如果存在
Cookie
或Authorization
标头,Varnish将不会从缓存中提供对象(请参阅vcl_recv
) - 如果存在
Set-Cookie
标头,Varnish将不会在缓存中存储对象(请参阅vcl_backend_response
) - 如果TTL为零或小于,Varnish将不会在缓存中存储对象(请参阅
vcl_backend_response
) - 如果
Cache-Control
标头包含no-store
,Varnish将不会在缓存中存储对象(请参见vcl_backend_response
) - 如果
Surrogate-Control
标头包含no-cache
、no-store
或private
,则Varnish不会在缓存中存储对象(请参见vcl_backend_response
) - 如果
Vary
标头通过*
对所有标头执行缓存变化,则Varnish不会将对象存储在缓存中(请参见vcl_backend_response
)
如何确保从缓存提供视频文件
在vcl_recv
中,您必须确保Varnish愿意从缓存中查找视频请求。实际上,这意味着要注意cookie。
我的建议是删除所有的cookie,除了你真正需要的cookie。下面的示例将删除除PHPSESSID
cookie之外的所有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)=", "; 1=");
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
将回退到内置VCL上,并且请求将从缓存中提供。
但在您的情况下,即使用户登录,您也希望从缓存中提供视频。这很好,因为视频是不受状态影响的静态文件。
问题是在请求上下文中无法指定Content-Type
信息。您必须使用URL。
举个例子:
sub vcl_recv {
if(req.url ~ "^/video") {
return(hash);
}
}
如果URL与^/video
正则表达式模式匹配,此代码段将绕过内置的VCL,并在缓存中显式查找对象。
如何确保视频文件存储在缓存中
当您在vcl_recv
中执行显式return(hash)
时,将创建哈希并进行缓存查找。但是,如果对象没有存储在缓存中,您仍然会有一个未命中,这将导致后端请求。
当后端响应返回时,它需要在缓存中存储一定的时间。考虑到内置的VCL,您必须确保没有指定零TTL,并且Cache-Control
响应标头必须返回可缓存的语法。
例如,如果我们想缓存一天的视频文件,我会这样设置Cache-Control
标头:
Cache-Control: public, max-age=86400
Varnish将尊重此标头,并根据max-age
语法将TTL设置为1天。
即使您没有指定Cache-Control
标头,Varnish仍会将其存储在缓存中,但存储时间为2分钟,这是默认的TTL。
以下是一个例子,其中Varnish不会将对象存储在缓存中,基于Cache-Control
标头:
Cache-Control: private, max-age=0, s-maxage=0 ,no-cache, no-store
如果这两个表达式中的任何一个在Cache-Control
中,Varnish将使对象不可缓存。
如果Set-Cookie
标头是响应的一部分,那么对象也将变得不可缓存。
如果您不能完全控制后端服务器返回的头,您仍然可以在VCL中碰碰运气。
这里有一个VCL片段,我们强制将对象存储在图像和视频的缓存中:
sub vcl_backend_response {
if(beresp.http.Content-Type ~ "^(image|video)/") {
set beresp.ttl = 1d;
unset beresp.http.set-cookie;
return (deliver);
}
}
此示例将去掉Set-Cookie
标头,将覆盖一天的TTL,并显式存储和传递对象。仅当Content-Type
响应标头以image/
或以video/
开始时才出现这种情况