HTTP кеширование

Природа насыщенных веб-приложений подразумевает, что они динамические. Вне зависимости от того, насколько эффективно ваше приложение, каждый запрос будет содержать больше работы, чем обслуживание статического файла. Обычно это нормально, но когда вам нужно, чтобы ваши запросы были молниеносно быстрыми, вам понадобится HTTP-кешироваие.

Кеширование на плечах титанов

C HTTP-кешированием, вы можете кешировать страницы целиком (т.е. ответ), и затем, в обход приложения, отдавать кэшированные данные для каждого запроса. Конечно же, это не всегда возможно применить для очень динамичных сайтов, или всё же возможно? С помощью Edge Side Includes (ESI) вы можете использовать силу HTTP-кеширования только для фрагментов вашего сайта.

Система кеширования Symfony отличается от других, так как она полагается на простоту и мощь HTTP-кеширования, как это определено в спецификации `RFC 7234 - Caching`_. Вместо того, чтобы изобретать кеширование заново, Symfony пользуется стандартом, который определяет базовые коммуникации в Web. Как только вы поймёте основополагающие модели HTTP валидации и истечения срока кэша, вы будете готовы к управлению системой кеширования Symfony.

Так как HTTP-кеширование используется не только Symfony, существует множество статей по данной теме. Если вы новичок в HTTP-кешировании, настоятельно рекомендуем вам прочитать статью Райана Томайко Вещи, которые делают кеши . Другим исчерпывающим источником является Учебное пособие по кешу от Марка Ноттингема.

Кеширование при помощи кеширующего шлюза

При HTTP-кешировании, кеш полностью отделён от вашего приложения и располагается между вашим приложением и клиентом, выполняющим запрос.

Работа кеша заключается в приёме запросов от клиента, и их передаче вашему приложению. Кеш также будет получать ответ от вашего приложения и перенаправлять его клиенту. Кеш является «посредником» в клиент-серверных коммуникациях между клиентом и вашим приложением.

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

Этот тип кeширования известен под именем "кeширующего HTTP шлюза". Существует много кeшеров такого типа, например: Varnish, Squid в режиме обратного прокси, а также обратный прокси Symfony.

Tip

Кеширующие шлюзы иногда называются кешами обратного прокси, суррогатными кешами или даже HTTP-акселераторами.

Обратный прокси Symfony

Symfony содержит обратный прокси (также называемый кеширующим шлюзом), написанный на PHP. Это кеш обратного прокси с неполным функционалом вроде Varnish, однако это отличный способ начать.

Tip

Чтобы узнать детали о настройке Varnish, см. How to Use Varnish to Speed up my Website.

Подключить прокси легко: каждое приложение имеет свое кеширующее ядро (AppCache), которое окружает ядро по умолчанию (AppKernel). Кеширующее ядро и есть обратным прокси.

Чтобы включить кеширование, измените код вашего фронт-контроллера. Вы также можете внести эти изменения в app_dev.php, чтобы добавить кеширование в окружение dev:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// web/app.php
use Symfony\Component\HttpFoundation\Request;

// ...
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();

// добавьте (или уберите комментарий) эту новую строчку!
// окружите ядро по умолчанию AppKernel с помощью AppCache
$kernel = new AppCache($kernel);

$request = Request::createFromGlobals();
// ...

Кеширующее ядро немедленно начнетдействовать как обратный прокси: кешировать ответы из вашего приложения и возвращать их клиенту.

Caution

Если вы используете опцию framework.http_method_override для прочтения HTTP-метода из параметра _method, см. ссылку выше для того, чтобы узнать, какие настройки вам стоит сделать.

Tip

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

1
error_log($kernel->getLog());

Объект AppCache имеет разумную конфигурацию по умолчанию, но вы можете хорошо настроить его с помощью набора опций, переопределив метод getOptions():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// app/AppCache.php
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;

class AppCache extends HttpCache
{
    protected function getOptions()
    {
        return array(
            'default_ttl' => 0,
            // ...
        );
    }
}

Чтобы увидеть весь список опций и их значения, см. Документацию HttpCache::__construct().

Когда вы находитесь в режиме отладки (из-за загрузки ядра debug, как в app_dev.php или вы вручную устанавливаете опцию debug как "true"), Symfony автоматически добавляет заголовок X-Symfony-Cache к ответу. Используйте это, чтобы получать информацию об попаданиях и промахах кеша.

Обратный прокси Symfony – это отличный инструмент для разработки или же выгрузки вашего сайта на виртуальный общий хостинг, где вы не можете установить ничего, кроме PHP кода. Однако, прокси на PHP никогда не будет быстрее прокси на С.

К счастью, так как все обратные прокси одинаковы по эффективности, вы должны имеь возможность перейти на что-то более совершенное вроде Varnish без каких- либо проблем. См. Как использовать Varnish.

Делаем ваши ответы HTTP-кешируемыми

Как только вы добавить кеш обратного прокси (например, как обратный прокси Symfony или Varnish), вы готовы кешировать ваши ответы. Чтобы сделать это, вам нужно сообщить вашему кешу, какие ответы являются кешируемыми и на какое время. Это делается путем установки заголовков кеша в ответе.

HTTP определяет четыре заголовка ответакеша, которые вы можете активировать:

  • Cache-Control
  • Expires
  • ETag
  • Last-Modified

Эти четыре заголовка используются для того, чтобы помочь вам кешировать ваши ответы с помощью двух разных моделей:

  1. Кеширование Expiration (окончания срока действия) Используется, чтобы кешировать весь ваш ответ на определенное количество времени (например, 24 часа). Просто, однако девалидация кеша более сложная.
  2. Кешировани Validation (валидации) Более сложная модель: используется, чтобы кешировать ваш ответ, но позволяет вам динамически инвалидировать его, как только ваш контент изменяется.

Все HTTP-заголовки, о которых вы будете читать, изобретены не Symfony! Они являются частью спецификации HTTP? которая используется сайтами по всей сети. Чтобы погрузиться в HTTP-кеширование, посмотрите документы RFC 7234 - Кеширование и `RFC 7232 - Условные запросы`_.

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

Кеширование срока хранения

Самый простой способ кешировать ответ - это кешировать его на определенное количество времени:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// src/AppBundle/Controller/BlogController.php
use Symfony\Component\HttpFoundation\Response;
// ...

public function indexAction()
{
    // создайте объект Response любым способом, например, отобразите шаблон
    $response = $this->render('blog/index.html.twig', []);

    // кешировать на 3600 секунд
    $response->setSharedMaxAge(3600);

    // (необязательно) установите пользовательскую директиву
    $response->headers->addCacheControlDirective('must-revalidate', true);

    return $response;
}

Благодаря этому новому коду, ваш HTTP-ответ будет иметь следующий заголовок:

1
Cache-Control: public, s-maxage=3600, must-revalidate

Он сообщает вашему обратному прокси HTTP кешировать этот ответ на 3600 секунд. Если кто-либо запросит этот URL опять раньше, чем через 3600 секунд, ваше приложение вообще не не будеть задействовано. Если вы используете обратный прокси Symfony, посмотрите на заголовок X-Symfony-Cache, для отладки информации о попаданиях и промахах кеша.

Tip

URI запроса используется в качестве ключа кеша (разве что вы варьируете).

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

Tip

На самом деле, вы можете вручную инвалидировать ваш кеш, но это не ялвяется частью спецификации HTTP-кеширования. См. Девалидация HTTP-кеша.

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

В конце-концов, для более детальной информации об окончании срока действия кеша, см. HTTP Cache Expiration.

Кеширование валидации

С кешированием с окончанием срока действия, вам просто нужно сказать "кешировать на 3600 секунд!". Но, когда кто-то обновляет кешированный контент, вы не сможете увидеть его до тех пор, пока не истечет срок действия кеша.

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

Чтобы узнать больше, см. HTTP Cache Validation.

Безопасные методы: Кеширование только запросов GET или HEAD

HTTP кэширование работает лишь для "безопасных" HTTP методов (таких как GET и HEAD). Это означает 2 вещи:

  • Не пытайтесь кешировать запросы PUT, POST или DELETE. Это не сработает, и по хорошей причине. Эти методы не должны быть использованы при изменении состояния вашего приложения (например, удалении поста блога). Их кеширование будет предотвращать некоторые запросы от попадания и изменения вашего приложения.
  • Вам никогда не стоит изменять состояние вашего приложение (например, обновлять пост блога), во время ответа на запрос GET или HEAD. Если эти запросы будут кешированы, будущие запросы могут никогда не попасть на ваш сервер.

Другие методы ответа

Класс Response содержит также множество других методов, относящихся к кешу. Вот самые полезные из них:

1
2
3
4
5
// Помечает ответ как "просроченный"
$response->expire();

// Форсировать возврат ответа 304 без контента
$response->setNotModified();

В дополнение к этому, все основные HTTP заголовки, относящиеся к кешу, могут быть установлены при помощи одного метода setCache():

1
2
3
4
5
6
7
8
9
// Установить заголовки для кэширования одним вызовом
$response->setCache(array(
    'etag'          => $etag,
    'last_modified' => $date,
    'max_age'       => 10,
    's_maxage'      => 10,
    'public'        => true,
    // 'private'    => true,
));

Аннуляция кеша

Аннуляция кеша не является частью HTTP-спецификации. Однако, она может быть очень ползеной для удаления различных записей HTTP-кеша, как только какой-либо контект вашего сайта обновляется.

Чтобы узнать больше, см. Аннуляция кеша.

Использование Edge Side Includes (ESI)

Когда на странице присутствуют динамические части, вам не удастся кешировать целые страницы, а придется это делать по частям. Читайте Working with Edge Side Includes, чтобы узнать, как сконфигурировать разные стратегии кеширования для определенных частей вашей страницы.

Заключение

Symfony создан таким образом, чтобы следовать проверенным «правилам движения» в HTTP. Кеширование - не исключение. Овладение системой кеширования Symfony, подразумевает близкое знакомство с моделями кэширования HTTP и их эффективное использование. Это означает, что вместо того, чтобы полагаться только на документацию Symfony и примеры кода, вы получаете доступ к целому миру знаний, относящихся к кешированию в HTTP и кеширующим шлюзам, таким как Varnish.

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