简体   繁体   English

如何指示 Varnish 根据响应 header 进行缓存?

[英]How do I instruct Varnish to cache based on response header?

I have a series of videos on various URLs across the site.我在整个站点的各种 URL 上有一系列视频。 I would like to cache them all with Varnish, even if the user is logged in .我想用 Varnish 缓存它们,即使用户已登录 I can use the VCL configuration in order to whitelist certain URLs for caching.我可以使用 VCL 配置将某些 URL 列入白名单以进行缓存。 But I don't know how I can whitelist all videos.但我不知道如何将所有视频列入白名单。

Is there a way to say that all responses that return with a content type of video/mp4 are cached?有没有办法说所有返回内容类型为 video/mp4 的响应都被缓存了?

Deciding to serve an object from cache, and deciding to store an object in cache are 2 different things in Varnish.决定从缓存中提供 object 和决定在缓存中存储 object 在 Varnish 中是两件不同的事情。 Both situations need to be accounted for.这两种情况都需要考虑。

Built-in VCL内置 VCL

In order to understand what happens out-of-the-box, you need to have a look at the following VCL file: https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin.vcl为了了解开箱即用的情况,您需要查看以下 VCL 文件: https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin。 vcl

This is the built-in VCL that is executed.这是执行的内置 VCL。 For each subroutine this logic is executed when you don't do an explicit return(xyz) in your VCL file for the corresponding subroutine.对于每个子例程,当您没有在 VCL 文件中为相应的子例程执行显式return(xyz)时,将执行此逻辑。

This means you have some sort of safety.net to protect you.这意味着您有某种 safety.net 来保护您。

From a technical perspective, the Varnish Compiler will add the built-in VCL parts to the subroutines you extend in your VCL prior to compiling the VCL file into a C code.从技术角度来看,在将 VCL 文件编译成 C 代码之前,Varnish 编译器会将内置的 VCL 部分添加到您在 VCL 中扩展的子例程中。

What do we learn from the built-in VCL我们从内置的 VCL 中学到了什么

The built-in VCL teaches us the following things when it comes to cacheability:内置的 VCL 告诉我们以下关于可缓存性的知识:

  • Varnish will only serve an object from cache for GET and HEAD requests (see vcl_recv ) Varnish 只会从缓存中为GETHEAD请求提供 object (参见vcl_recv
  • Varnish will not serve an object from cache if a Cookie or Authorization header is present (see vcl_recv )如果存在CookieAuthorization header,清漆将不会从缓存中提供 object (请参阅vcl_recv
  • Varnish will not store an object in cache if a Set-Cookie header is present (see vcl_backend_response )如果存在Set-Cookie header,清漆将不会在缓存中存储 object (请参阅vcl_backend_response
  • Varnish will not store an object in cache if TTL is zero or less (see vcl_backend_response )如果 TTL 为零或更小,清漆将不会在缓存中存储 object (请参阅vcl_backend_response
  • Varnish will not store an object in cache if the Cache-Control header contains no-store (see vcl_backend_response )如果Cache-Control header 包含no-store ,则 Varnish 不会将 object 存储在缓存中(参见vcl_backend_response
  • Varnish will not store an object in cache if the Surrogate-Control header contains no-cache , no-store or private (see vcl_backend_response )如果Surrogate-Control header 包含no-cacheno-storeprivate (参见vcl_backend_response ,Varnish 将不会在缓存中存储 object
  • Varnish will not store an object in cache if the Vary header performs cache variations on all headers via a * (see vcl_backend_response )如果Vary header 通过*对所有标头执行缓存变化,则 Varnish 不会将 object 存储在缓存中(请参阅vcl_backend_response

How to make sure video files are served from cache如何确保从缓存中提供视频文件

In vcl_recv you have to make sure Varnish is willing to lookup video requests from cache.vcl_recv中,您必须确保 Varnish 愿意从缓存中查找视频请求。 In practical terms, this means taking care of the cookies.实际上,这意味着要处理 cookies。

My advice would be to remove all cookies, except the ones you really need.我的建议是删除所有 cookies,除了你真正需要的那些。 The example below will remove all cookies, except the PHPSESSID cookie, which is required by my backend:下面的示例将删除所有 cookies,但我的后端需要的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)=", "; \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;
    }
}

This example will remove tracking cookies from the request, which is fine, because they are processed by Javascript.此示例将从请求中删除跟踪 cookies,这很好,因为它们由 Javascript 处理。

When the PHPSESSID cookie is not set, vcl_recv will fall back on the built-in VCL , and the request will be served from cache.当未设置PHPSESSID cookie 时, vcl_recv将退回到内置 VCL ,请求将从缓存中获取。

But in your case, you want them to be served from cache, even when users are logged in. This is fine, because videos are static files that aren't influenced by state.但在您的情况下,您希望从缓存中提供它们,即使用户已登录。这很好,因为视频是不受 state 影响的 static 文件。

The problem is that in the request context you cannot specify Content-Type information.问题是在请求上下文中您不能指定Content-Type信息。 You'll have to use the URL.您必须使用 URL。

Here's example:这是例子:

sub vcl_recv {
    if(req.url ~ "^/video") {
        return(hash);
    }
}

This snippet will bypass the built-in VCL , and will explicitly look the object up in cache, if the URL matches the ^/video regex pattern.此代码段将绕过内置 VCL ,如果 URL 与^/video正则表达式模式匹配,则会在缓存中明确查找 object。

How to make sure video files are stored in cache如何确保视频文件存储在缓存中

When you do an explicit return(hash) in vcl_recv , the hash will be created and a cache lookup takes place.当您在vcl_recv中执行显式return(hash)时,将创建 hash 并进行缓存查找。 But if the object is not stored in cache, you'll still have a miss, which results in a backend request.但是如果 object 没有存储在缓存中,你仍然会错过,这会导致后端请求。

When the backend response comes back, it needs to be stored in cache for a certain amount of time.当后端响应返回时,需要在缓存中保存一定时间。 Given the built-in VCL , you have to make sure you don't specify a zero-TTL, and the Cache-Control response header must return cacheable syntax.给定内置 VCL ,您必须确保未指定零 TTL,并且Cache-Control响应 header 必须返回可缓存语法。

This is how I would set the Cache-Control header if for example we want to cache video files for a day:例如,如果我们想要缓存一天的视频文件,这就是我设置Cache-Control header 的方式:

Cache-Control: public, max-age=86400

Varnish will respect this header, and will set the TTL to 1 day based on the max-age syntax. Varnish 会尊重这个 header,并会根据max-age语法将 TTL 设置为 1 天。

Even if you don't specify a Cache-Control header, Varnish will still store it in cache, but for 2 minutes, which is the default TTL.即使您不指定Cache-Control header,Varnish 仍会将其存储在缓存中,但持续时间为 2 分钟,这是默认的 TTL。

Here's an example where Varnish will not store the object in cache, based on the Cache-Control header:这是一个 Varnish 不会将 object 存储在缓存中的示例,基于Cache-Control header:

Cache-Control: private, max-age=0, s-maxage=0 ,no-cache, no-store

If either of these expressions is in Cache-Control , Varnish will make the object uncacheable.如果这些表达式中的任何一个在Cache-Control中,Varnish 将使 object 不可缓存。

If Set-Cookie headers are part of the response, the object becomes uncacheable as well.如果Set-Cookie标头是响应的一部分,则 object 也变得不可缓存。

In case you don't have full control over the headers that are returned by the backend server, you can still force your luck in VCL.如果您不能完全控制后端服务器返回的标头,您仍然可以在 VCL 中靠运气。

Here's a VCL snippet where we force objects to be stored in cache for images and videos:这是一个 VCL 片段,我们强制将对象存储在图像和视频的缓存中:

sub vcl_backend_response {
    if(beresp.http.Content-Type ~ "^(image|video)/") {
        set beresp.ttl = 1d;
        unset beresp.http.set-cookie;
        return (deliver);
    }
}

This example will strip off Set-Cookie headers, will override the TTL to a day, and it will explicitly store and deliver the object. This is only the case when the Content-Type response headers either starts with image/ , or with video/此示例将剥离Set-Cookie标头,将 TTL 覆盖为一天,并将显式存储和传送 object。仅当Content-Type响应标头以image/或以video/开头时才会出现这种情况

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM