HTTP-кешування

Дата оновлення перекладу 2022-12-15

HTTP-кешування

Природа насичених веб-додатків передбачає, що вони динамісні. Незалежно від того, наскільки ефективний ваш додаток, кожний запит буде містити більше роботи, ніж обслуговування статичного файлу. Зазвичай це нормально, але коли вам потрібно, щоб ваші запити були блискавично швидкими, вам знадобиться HTTP-кешування.

Кешування на плечах титанів

З HTTP-кешуванням ви також можете кешувати сторінки цілком (тобто, відповідь), а потім, в обхід додатку, віддавати кешовані дані для кожного запиту. Звичайно ж, це не завжди можна застосувати для дуже динамічних сайтів. Чи все ж можливо? За допомогою Включень крайніх сторін (ESI) ви можете використати силу HTTP-кешування лише для фрагментів вашого сайту.

Система кешування Symfony відрізняється від інших, так як вона покладається на простоту та потужність HTTP-кешування, як це визначено у специфікації RFC 7234 - Кешування. Замість того, щоб винаходити кешування наново, Symfony користується стандартом, який визначає базові комунікації в мережі. Як тільки ви зрозумієте основні моделі HTTP валідації та закінчення строку кешу, ви будете готові до керування системою кешування Symfony.

Так як HTTP-кешування використовується не лише Symfony, існує безліч статей на дану тему. Якщо ви новачок в HTTP-кешуванні, наполегливо рекомендуємо вам прочитати статтю Райана Томайко Речі, які роблять кеші . Іншим вичерпним джерелом є Туторіал з кешу від Марка Ноттінгема.

Кешування за допомогою кешуючого шлюзу

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

Робота кешу полягає у прийманні запитів від клієнта та їх передачі вашому додатку. Кеш також отримуватиме відповідь від вашого додатку та перенаправлятиме його клієнту. Кеш є "посередником" у клієнт-серверних комунікаціях між клієнтом та вашим додатком.

На шляху, кеш зберігатиме кожну відповідь, яку вважає "кешованою" (див. Вступ в HTTP-кешування ). Якщо цей же ресурс буде запитаний ще раз, кеш відправить збережену (кешовану) відповідь клієнту, повністю ігноруючи ваш додаток.

Цей тип кешування відомий під назвою "кешуючий шлюз HTTP шлюза". Існує багато кешерів такого типу, наприклад: Varnish, Squid у режимі зворотного проксі, а також зворотний проксі Symfony.

Tip

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

Зворотний проксі Symfony

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

Tip

Щоб дізнатися деталі про налаштування Varnish, див. Як використовувати Varnish для прискорення мого сайту.

Використайте опцію framework.http_cache, щоб включити проксі для середовища виробництва :

  • YAML
  • XML
  • PHP
1
2
3
4
# config/packages/framework.yaml
when@prod:
    framework:
        http_cache: true

Ядро негайно почне поводитися як зворотний проксі: кешувати відповіді з вашого додатку та повертати їх клієнту.

Проксі має розумну конфігурацію за замовчуванням, але вона може бути тонко налаштована через набір опцій .

У режимі налагодження Symfony автоматично додає заголовок X-Symfony-Cache до відповіді. Ви можете також використати опцію конфігурації trace_level та встановитти її як none, short або full, щоб додати цю інформацію.

short додасть інформацію лише для головного запиту. Вона написана ємно, тому записувати інформацію у файли логів на вашому сервері легко. Наприклад, в Apache ви можете використати %{X-Symfony-Cache}o у твердженнях формату LogFormat. Ця інформація може бути використана для вилучення загальної інформації про ефективність кешу ваших маршрутів.

Tip

Ви можете змінити імʼя заголовку, використовуваного для інформації інформації трасування, використовуючи опцію конфігурації trace_header.

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

На щастя, так як всі зворотні проксі однакові за ефективністю, ви повинні мати можливість перейти на щось досконаліше на кшталт Varnish без будь-яких проблем. Див. Як використовувати Varnish.

Робимо ваші відповіді HTTP-кешованими

Як тільки ви додасте кеш зворотного проксі (наприклад, як зворотний проксі Symfony або Varnish), ви готові кшеувати ваші відповіді. Щоб зробити це, вам потрібно повідомити вашому кешу, які відповіді є кешованими і на який час. Це робиться шляхом установки заголовків кешу у відповіді.

HTTP визначає чотири заголовки відповідей кешу, які ви можете активувати:

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

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

  1. Кешування закінчення строку дії Використовується, щоб кешувати всю вашу відповідь на визначену кількість часу (наприклад, 24 години). Просто, але девалідація кешу складніша.
  2. Кешування валідації Складніша модель: використовується, щоб кешувати вашу відповідь, але дозволяє вамм динамічно інвалідувати її, як тільки ваш контент зміниться.

Всі HTTP-заголовки, про які ви читатимете, винайдені не Symfony! Вони є частиною специфікації HTTP, яка використовується сайтами по всій мережі. Щоб зануритися в HTTP-кешування, перегляньте документи RFC 7234 - Кешування та RFC 7232 - Умовні запити.

Вам, як веб-розробнику, наполегливо рекомендується прочитати цю специфікацію. Її простота та сила, навіть більше ніж через 10 років після написання, безцінні. Не бійтеся зовнішнього вигляду специфікації - її зміст набагато краще, ніж обкладинка!

Кешування строку дії

Найпростіший спосіб кешувати відповідь - це кешувати її на певну кількість часу:

  • Attributes
  • PHP
1
2
3
4
5
6
7
8
9
// src/Controller/BlogController.php
use Symfony\Component\HttpKernel\Attribute\Cache;
// ...

#[Cache(public: true, maxage: 3600, mustRevalidate: true)]
public function index(): Response
{
    return $this->render('blog/index.html.twig', []);
}

6.2

Атрибут #[Cache()] було представлено в Symfony 6.2.

Завдяки цьому новому коду, ваша 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-кешу.

Кешування валідації

З кешуванням закінчення строку дії, вам просто потрібно сказати "кешувати протягом 3600 секунд!". Але коли хтось оновлює кешований зміст, ви не зможете побачити його до тих пір, поки не закінчиться строк дії кешу.

Якщо вам потрібно побачити оновлений зміст одразу ж, вам потрібно або інвалідувати ваш кеш, або викристати модель кешування валідації.

Щоб дізнатися більше, див.. Валідація HTTP-кешу.

Безпечні методи: Кешування лише запитів GET або HEAD

HTTP-кешування працює тільки для "безпечних" HTTP-методів (таких як GET і HEAD). Це означає:

  • Не намагайтесь кешувати запити PUT або DELETE. Це не спрацює, і з гарної причини. Ці методи не повинні бути використані при зміні стану вашого додатку (наприклад, видаленні поста блогу). Їх кешування буде запобігати попадання деяких запитів або їх зміні вашого додатку.
  • Запити POST зазвичай вважаються некешованими, але їх можна кешувати, якщо вони містять ясну інформацію свіжості. Однак, кешування POST не реалізується широко, тому вам варто цього уникати за можливості.
  • Вам ніколи не варто змінювати стан вашого додатку (наприклад, оновлювати пост блогу) під час відповіді на запит GET або HEAD. Якщо ці запити будуть кешовані, майбутні запити можуть ніколи не потрапити на ваш сервер.

Більше методів відповіді

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

1
2
3
4
5
// відмічає відповідь як "прострочену"
$response->expire();

// форсує повернення відповіді 304 без змісту
$response->setNotModified();

На додаток до цього, всі основні HTTP-заголовки, що відносяться до кешу, можуть бути встановлені за допомогою одного методу setCache():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// використайте цей метод, щоб встановити декілька налаштувань кешування в одному виклику
// (цей приклад перелічує всі доступні налашштування кешу)
$response->setCache([
    'must_revalidate'  => false,
    'no_cache'         => false,
    'no_store'         => false,
    'no_transform'     => false,
    'public'           => true,
    'private'          => false,
    'proxy_revalidate' => false,
    'max_age'          => 600,
    's_maxage'         => 600,
    'immutable'        => true,
    'last_modified'    => new \DateTime(),
    'etag'             => 'abcdef'
]);

Tip

Всі ці опції також доступні при використанні атрибуту #[Cache()].

Інвалідація кешу

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

Щоб дізнатися більше, див. Інвалідація кешу.

Використання Включень крайніх сторін (ESI)

Коли на сторінці присутні динамічні частини, вам не вдатсться кешувати цілі сторінки, а доведеться робити це частинами. Читайте Робота з включеннями крайніх сторін, щоб дізнатися, як сконфігурувати різні стратегії кешування для певних частин вашої сторінки.

HTTP-кешування та сесії користувача

Коли сесія розпочинається під час запиту, Symfony перетворює відповідь на приватну некешовану відповідь. Це найкраща поведінка за замовчуванням, щоб не кешувати особисту інформацію користувача (наприклад, корзину покупок, деталі профілю користувача і т.д.) і не оголити її іншим відвідувачам.

Однак, навіть запити, що отримують переваги від сесії, можна кешувати за деяких обставин. Наприклад, інформація, повʼязана з якоюсь групою користувачів має кешуватися для всіх користувачів, що належать до цієї групи. Обробка таких просунутих сценаріїв кешування знаходиться поза межами Symfony, але вони можуть бути вирішені за допомогою FOSHttpCacheBundle.

Для того, щоб відключити поведінку Symfony за замовчуванням, яка робить запити, що використовують сесію, некешованими, додайте наступний внутрішній заголовок до вашої відповіді, і Symfony не буде її змінювати:

1
2
3
use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;

$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');

Висновок

Symfony створена таким чином, щоб дотримуватися перевірених "правил дорожнього руху" в HTTP. Кешування - не виключення. Опанування системи кешування Symfony передбачає близьке знайомство з моделями кешування HTTP та їх ефективне використання. Це озанчає, що замість того, щоб покладатися лише на документацію Symfony та приклади коду, ви отримуєте доступ до цілого світу знань, що відносяться до кешування в HTTP та кешуючих шлюзів, таких як Varnish.