Как мне указать Varnish кэшировать на основе заголовка ответа?

#caching #varnish

#кэширование #varnish

Вопрос:

У меня есть серия видеороликов по различным URL-адресам на сайте. Я хотел бы кэшировать их все с помощью Varnish, даже если пользователь вошел в систему. Я могу использовать конфигурацию VCL, чтобы внести в белый список определенные URL-адреса для кэширования. Но я не знаю, как я могу внести все видео в белый список.

Есть ли способ сказать, что все ответы, которые возвращаются с типом контента video / mp4, кэшируются?

Ответ №1:

Решение обслуживать объект из кэша и решение сохранить объект в кэше — это 2 разные вещи в Varnish. Необходимо учитывать обе ситуации.

Встроенный VCL

Чтобы понять, что происходит «из коробки», вам нужно взглянуть на следующий файл VCL: https://github.com/varnishcache/varnish-cache/blob/master/bin/varnishd/builtin.vcl

Это встроенный VCL, который выполняется. Для каждой подпрограммы эта логика выполняется, когда вы не выполняете явное return(xyz) в вашем файле VCL для соответствующей подпрограммы.

Это означает, что у вас есть какая-то система безопасности для защиты.

С технической точки зрения компилятор Varnish добавит встроенные части VCL к подпрограммам, которые вы расширяете в своем VCL, перед компиляцией файла VCL в код C.

Что мы узнаем из встроенного VCL

Встроенный VCL учит нас следующим вещам, когда дело доходит до кэширования:

  • Varnish будет обслуживать только объект из кэша для GET HEAD запросов и (см. vcl_recv )
  • Varnish не будет обслуживать объект из кэша, если Cookie Authorization присутствует заголовок or (см. vcl_recv )
  • Varnish не сохранит объект в кэше, если Set-Cookie присутствует заголовок (см. vcl_backend_response )
  • Varnish не сохранит объект в кэше, если TTL равен нулю или меньше (см. vcl_backend_response )
  • Varnish не сохранит объект в кэше, если Cache-Control заголовок содержит no-store (см. vcl_backend_response )
  • Varnish не сохранит объект в кэше, если Surrogate-Control заголовок содержит no-cache no-store или private (см. vcl_backend_response )
  • Varnish не сохранит объект в кэше, если Vary заголовок выполняет изменения кэша для всех заголовков через * (см. 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)=", "; 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);
    }
}
  

Этот фрагмент будет обходить встроенный VCL и явно искать объект в кэше, если URL-адрес соответствует шаблону ^/video регулярных выражений.

Как убедиться, что видеофайлы хранятся в кэше

Когда вы выполняете явный return(hash) vcl_recv ввод, будет создан хэш и будет выполнен поиск в кэше. Но если объект не сохранен в кэше, у вас все равно будет ошибка, что приведет к внутреннему запросу.

Когда серверный ответ возвращается, его необходимо сохранить в кэше в течение определенного времени. Учитывая встроенный VCL, вы должны убедиться, что вы не указали нулевой TTL, а заголовок Cache-Control ответа должен возвращать кэшируемый синтаксис.

Вот как я бы установил Cache-Control заголовок, если, например, мы хотим кэшировать видеофайлы в течение дня:

 Cache-Control: public, max-age=86400
  

Varnish будет учитывать этот заголовок и установит TTL равным 1 дню на основе max-age синтаксиса.

Даже если вы не укажете 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 для a day, и он явно сохранит и доставит объект. Это только в том случае, когда заголовки Content-Type ответов начинаются либо с image/ , либо с video/