Ворклог по задаче "Настроить кеширование varnish"

24 сент. 2026 г., 12:49:54

Настроено кеширование статических ресурсов через Varnish

Для сайта gorodskie-bani.ru настроено проксирование статических ресурсов через Varnish с TTL 7 дней. Через кеш проходят JS, CSS, шрифты, изображения, иконки и ресурсы /styles/ от tileserver. Динамические страницы намеренно не кешируются и продолжают обрабатываться приложением напрямую (return (pass)).

Зачем это нужно

Основная задача кеширования — отдавать неизменяемые и редко меняющиеся ресурсы не из Node.js-приложения и tileserver при каждом запросе, а непосредственно из памяти/кеша Varnish.

Это даёт сайту несколько практических преимуществ:

  • Снижается время отдачи статики. После первого запроса ресурс попадает в кеш, последующие запросы обслуживаются Varnish без обращения к backend.
  • Уменьшается нагрузка на приложение и tileserver. JS, CSS, изображения, шрифты и стили карты не создают повторную нагрузку на backend-контейнеры.
  • Повышается стабильность под нагрузкой. При одновременных заходах пользователей большая часть запросов к статике обслуживается на уровне кеширующего прокси.
  • Ускоряется загрузка страниц для пользователей. Быстрая отдача CSS, JS, шрифтов и изображений уменьшает ожидание ресурсов, необходимых для отрисовки страницы.
  • Создаётся положительный технический эффект для SEO. Скорость загрузки и пользовательские метрики производительности, в том числе связанные с Core Web Vitals, являются частью технического качества сайта. Varnish не меняет позиции в поиске напрямую, но помогает уменьшить сетевые задержки и нагрузку на origin, что создаёт более стабильные условия для быстрой загрузки и обхода сайта поисковыми роботами.

Конфигурация Varnish

Настроены два backend:

  • основной backend приложения — gorodskie-bani--agent-app-1:3000;
  • отдельный backend tileserver — gorodskie-bani-ru-tileserver-1:80.
vcl 4.1;

backend default {
    .host = "gorodskie-bani--agent-app-1";
    .port = "3000";
}

backend tileserver {
    .host = "gorodskie-bani-ru-tileserver-1";
    .port = "80";
}

В vcl_recv запросы к /styles/ отправляются в tileserver. Для кешируемых ресурсов Cookie удаляются, чтобы пользовательские cookies не дробили кеш и не мешали повторному использованию одного объекта разными запросами.

sub vcl_recv {
    if (req.url ~ "^/styles/") {
        set req.backend_hint = tileserver;
        unset req.http.Cookie;
        return (hash);
    }
    if (req.url ~ "\.(js|css|woff2?|ttf|eot|svg|ico|png|jpg|jpeg|gif|webp|avif)(\?.*)?$") {
        unset req.http.Cookie;
        return (hash);
    }
    return (pass);
}

Все остальные запросы идут через pass, то есть HTML и динамические ответы приложения этим правилом не кешируются. Это снижает риск отдачи устаревшего персонализированного или динамического контента.

Ключ кеша строится по URL и host:

sub vcl_hash {
    hash_data(req.url);
    hash_data(req.http.host);
    return (lookup);
}

Это позволяет раздельно хранить ресурсы разных URL и не смешивать кеш между хостами. Query string остаётся частью req.url, поэтому версии ассетов с cache-busting параметрами получают отдельные записи кеша.

Для /styles/ и статических файлов задан TTL 7 дней, а Set-Cookie удаляется из кешируемых backend-ответов:

sub vcl_backend_response {
    if (bereq.url ~ "^/styles/") {
        set beresp.ttl = 7d;
        unset beresp.http.Set-Cookie;
    }
    if (bereq.url ~ "\.(js|css|woff2?|ttf|eot|svg|ico|png|jpg|jpeg|gif|webp|avif)(\?.*)?$") {
        set beresp.ttl = 7d;
        unset beresp.http.Set-Cookie;
    }
}

TTL 7 дней позволяет долго обслуживать повторные запросы из Varnish, при этом стандартный подход с версионированными именами файлов или query-параметрами позволяет получать новую версию ресурса после деплоя без ожидания истечения старого кеша.

Для диагностики добавлены служебные заголовки X-Cache и X-Cache-TTL:

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }
    set resp.http.X-Cache-TTL = obj.ttl;
}

По ним можно быстро проверить фактическую работу кеша: первый запрос обычно отдаётся как MISS, последующие — как HIT, а X-Cache-TTL показывает оставшееся время жизни объекта.

Маршрутизация Traefik

Чтобы нужные запросы действительно попадали в Varnish, в Traefik добавлены отдельные роутеры с высоким приоритетом.

Статические файлы:

gorodskie-bani.ru-static:
  rule: 'Host(`gorodskie-bani.ru`) && PathRegexp(`^.*\.(js|css|woff2?|ttf|eot|svg|ico|png|jpg|jpeg|gif|webp|avif)$`)'
  entryPoints:
    - websec
  service: gorodskie-bani.ru-varnish
  tls:
    certResolver: letsencrypt
  priority: 200

Ресурсы /styles:

gorodskie-bani.ru-styles:
  rule: "Host(`gorodskie-bani.ru`) && PathPrefix(`/styles`)"
  entryPoints:
    - websec
  middlewares: []
  service: gorodskie-bani.ru-varnish
  tls:
    certResolver: letsencrypt
  priority: 200

Таким образом, Traefik отделяет кешируемые запросы на входе и передаёт их в сервис Varnish, после чего Varnish либо отдаёт объект из кеша, либо получает его с соответствующего backend и сохраняет на 7 дней.

Итог для сайта и SEO

В результате статическая часть gorodskie-bani.ru обслуживается через отдельный кеширующий слой. Это уменьшает количество обращений к приложению и tileserver, ускоряет повторную загрузку ресурсов и делает время ответа более стабильным при росте трафика.

Для SEO это полезно прежде всего как инфраструктурная оптимизация производительности: браузер быстрее получает критические CSS/JS/шрифты/изображения, backend меньше конкурирует за ресурсы со статическими запросами, а сайт устойчивее сохраняет нормальную скорость ответа под нагрузкой. В совокупности это помогает техническому качеству сайта и пользовательскому опыту, которые важны для поисковой видимости и эффективности органического трафика.

24.09.2026