Как использовать Varnish для ускорения моего сайта

Так как кеш Symfony использует стандартные HTTP кеш заголовки, Symfony Reverse Proxy может быть с лёгкостью заменён любым другим обратным прокси. Varnish - это мощный открытый HTTP-акселератор, способный быстро обслуживать кешированное содержание, включая поддержку Edge Side Includes.

Заставляем Symfony доверять обратному прокси

Varnish автоматически пересылает IP как X-Forwarded-For и оставляет загловок X-Forwarded-Proto в запросе. Если вы не сконфигурируете Varnish как доверенный прокси, то Symfony будет видеть все запросы, как исходящие от незащищённых HTTP соединений хоста Varnish, а не от реального клиента.

Не забудьте вызвать метод Request::setTrustedProxies() в вашем фронт-контроллере, чтобы Varnish выглядел как доверенный прокси и были использованы заголовки X-Forwarded-*.

Маршрутизация и заголовки X-FORWARDED

Чтобы убедиться в том, что маршрутизатор Symfony правильно генерирует URL с Varnish, должен присутствовать заголовок X-Forwarded-Port, чтобы Symfony использовала правильный номер порта.

Этот номер порта соответствует тому, что использует ваша установка для извлечения внешних связей (80 - значение по умолчанию для HTTP-соединений). Если приложение также принимает HTTP-соединения, то может быть ещё один прокси (так как Varnish сам не делает HTTPS) в порту HTTPS по умолчанию 443, который обрабатывает завершение SSL и переселыает запросы как HTTP-запросы в Varnish с заголовком X-Forwarded-Proto. В этом случае, вам нужно добавить следующий отрезок конфигурации:

1
2
3
4
5
6
7
sub vcl_recv {
    if (req.http.X-Forwarded-Proto == "https" ) {
        set req.http.X-Forwarded-Port = "443";
    } else {
        set req.http.X-Forwarded-Port = "80";
    }
}

Гарантия последовательного поведения кеширования

Varnish использует заголовки кеша, отправленные вашим приложением, чтобы определить, как кешировать содержимое. Однако, версии Varnish до 4 не уважали Cache-Control: no-cache, no-store и private. Чтобы гарантировать последовательное поведение, используйте следуюзую конфигурацию, если вы всё ещё используете Varnish 3:

  • Varnish 3
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    sub vcl_fetch {
        /* По умолчанию, Varnish3 игнорирует Cache-Control: no-cache и private
           https://www.varnish-cache.org/docs/3.0/tutorial/increasing_your_hitrate.html#cache-control
         */
        if (beresp.http.Cache-Control ~ "private" ||
            beresp.http.Cache-Control ~ "no-cache" ||
            beresp.http.Cache-Control ~ "no-store"
        ) {
            return (hit_for_pass);
        }
    }
    

Tip

Вы можете увидеть поведение Varnish по умолчанию в форме VCL-файла: default.vcl для Varnish 3, builtin.vcl для Varnish 4.

Активация включений крайней стороны (Edge Side Includes (ESI))

Как объясняется в статье об ESI, Symfony определяет, общается она с обратным прокси, понимающим ESI, или нет. Когда вы используете обратный прокси Symfony, вам не нужно ничего делать. Но чтобы заставить Varnish разрешать ESI-теги вместо Symfony, вам нужна некоторая конфигурация в Varnish. Symfony использует заголовок Surrogate-Capability из Edge Architecture, описанный Akamai.

Note

Varnish поддерживает только атрибут src для ESI-тегов (атрибуты onerror и alt игнорируются).

Для начала, сконфигурируйте Varnish так, чтобы он афишировал свою поддержку ESI путём добавления заголовка Surrogate-Capability в запросы, пересылаемые приложению выходного буфера:

1
2
3
4
sub vcl_recv {
    // Добавить заголовок Surrogate-Capability, чтобы афишировать поддержку ESI.
    set req.http.Surrogate-Capability = "abc=ESI/1.0";
}

Note

Часть заголовка abc неважна, кроме случаев, если у вас множество "сурогатов", которые должны афишировать свои возможности. Смотрите `Заголовок Surrogate-Capability`_, чтобы узнать детали.

Далее, оптимизируйте Varnish так, чтобы он анализировал содержимое ответа только тогда, когда в нём есть хотя бы один ESI-тег, проверяя заголовок Surrogate-Control, который Symfony добавляет автоматически:

  • Varnish 4
    1
    2
    3
    4
    5
    6
    7
    sub vcl_backend_response {
        // Проверить подтверждение ESI и удалить заголовок Surrogate-Control
        if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
            unset beresp.http.Surrogate-Control;
            set beresp.do_esi = true;
        }
    }
    
  • Varnish 3
    1
    2
    3
    4
    5
    6
    7
    sub vcl_fetch {
        // Проверить подтверждение ESI и удалить заголовок Surrogate-Control
        if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
            unset beresp.http.Surrogate-Control;
            set beresp.do_esi = true;
        }
    }
    

Tip

Если вы последовали совету о гарантировании последовательного поведеия кеширования, то эти VCL-функции уже существуют. Просто добавьте код к концу функции, они не будут мешать друг другу.

Инвалидация кеширования

Если вы хотите кешировать содержимое, которое часто меняется, и всё равно отправлять пользователям наиболее свежую версию, то вам нужно инвалидировать это содержимое. В то время, как инвалидация кеширования позволяет вам извлекать содержимое из вашего прокси до того, как истечёт срок действия, она добавляет сложности вашей установке кеширования.

Tip

FOSHttpCacheBundle открытого доступа избавляет от головной боли с инвалидацией, помогая вам организовать вашу установку кеширования и инвалидации.

Документация FOSHttpCacheBundle разъясняет, как сконфигурировать Varnish и другие обратные прокси для инвалидации кеширования.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.