Чому CDN не кешує статичний файл: перевіряємо заголовки відповіді

CDNHTTP-кешуванняDevOps

Коробка з персональною биркою оминає сортувальний лоток і прямує до перевантаженого сервера

Сервер уже масштабують, а файл усе одно не кешується

Після релізу зростають затримка й кількість запитів до сервера-джерела. Команда додає ресурси, але основний трафік створюють зображення, CSS або інші файли, які мав би віддавати CDN.

Тоді хтось відкриває один URL статичного файла й кілька разів оновлює сторінку. Кожне оновлення знову видно в журналі застосунку. CDN присутній у маршруті, але не знімає навантаження.

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

Почніть з одного контрольного URL

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

Виконайте два однакові GET-запити без очищення кешу між ними:

curl -sS -D - -o /dev/null https://example.com/assets/app.4f31.css
curl -sS -D - -o /dev/null https://example.com/assets/app.4f31.css

Збережіть Cache-Control, Set-Cookie, Vary, ETag, Last-Modified, Age і заголовок стану кешу вашого CDN. Одночасно перевірте, чи обидва запити потрапили до журналу сервера-джерела. Назва заголовка стану залежить від постачальника, тому важливі не назва, а послідовність результатів.

CDN ухвалює рішення у два моменти

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

Після відповіді сервера-джерела з’являється друга група доказів: код стану та заголовки відповіді. Саме тут файл із безпечною адресою може виявитися непридатним для спільного кешу.

Сучасні засоби керування CDN можуть застосовувати правила і на цьому етапі. Нова можливість Cloudflare є актуальним прикладом, але сама модель не залежить від одного постачальника. Водночас правило відповіді не виправить пропуск кешу, якщо CDN ще на етапі запиту визнав запит непридатним для кешування: перевіряти треба обидва рішення.

Що означають підозрілі заголовки

  • Set-Cookie часто змушує CDN не зберігати відповідь за типовими правилами продукту. Для статичного файла він може з’явитися через спільне проміжне програмне забезпечення, яке створює сесію на кожному маршруті. Не видаляйте заголовок правилом, доки не доведете, що файл cookie справді випадковий і не впливає на вміст.
  • Cache-Control: no-store забороняє зберігати відповідь. private не дозволяє спільному кешу використовувати її для різних користувачів. no-cache дозволяє збереження, але вимагає перевірки перед повторним використанням.
  • Vary указує, які заголовки запиту обирають варіант відповіді. Відсутній або неправильно підтриманий Vary загрожує видачею не того варіанта, а надто широкий — низькою часткою влучань у кеш. Підтримка окремих значень залежить від CDN.
  • ETag і Last-Modified є валідаторами. Після завершення свіжості CDN може надіслати умовний запит і отримати 304 Not Modified. Це зменшує обсяг даних, але запит усе одно доходить до сервера-джерела.
  • Age передає оцінку кількості секунд від створення або останньої успішної перевірки відповіді на сервері-джерелі. Якщо значення не зростає або постійно скидається, зіставте його зі станом кешу та журналами.

Розділіть маршрути до виправлення

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

Спільний динамічний контент також однаковий для користувачів, але швидко застаріває. Йому може підійти короткий час свіжості та подальша ревалідація.

Варіантний спільний контент може залежати від мови або регіону, але не від конкретної людини. Його можна кешувати, лише якщо CDN розрізняє варіанти окремими URL або ключами кешу.

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

Виправляйте сервер-джерело, а правило CDN залиште вузьким

Основне виправлення варто робити там, де виникає неправильний заголовок — зазвичай на сервері-джерелі. Для версійованої публічної статики типовим кандидатом буде:

Cache-Control: public, max-age=31536000, immutable

Такий маршрут не повинен випадково повертати Set-Cookie. Директива immutable доречна лише тоді, коли зміна вмісту створює новий URL.

Для спільного динамічного контенту використовуйте коротше s-maxage і валідатори, якщо відповідь гарантовано однакова. Для варіантного контенту перевірте, що ключ кешу справді розділяє варіанти. Для персоналізованого залишайте private або no-store відповідно до вимог застосунку.

Якщо сервер-джерело зараз змінити неможливо, правило на межі CDN може бути тимчасовим рішенням. Обмежте його конкретним хостом, шляхом, типом відповіді та успішним кодом стану. Не прибирайте Set-Cookie і не переписуйте private глобально.

Перевірте зміну через канаркове впровадження

Спочатку застосуйте правило до одного маршруту або малої частини трафіку. Запишіть початкові значення частки влучань у кеш, кількості запитів до сервера-джерела, затримки та помилок. Після зміни перевірте також свіжість файла й відповідність його контрольній сумі.

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

Небезпечні скорочення

  • Не примушуйте кешувати все за розширенням файла: маршрут може повертати сторінку входу або помилку.
  • Не вважайте 304 повним влучанням у кеш: для нього могла знадобитися ревалідація на сервері-джерелі.
  • Не кешуйте мовні чи регіональні варіанти спільно, доки не перевірите Vary, окремі URL або ключ кешу.
  • Не встановлюйте довгу свіжість для URL, вміст якого змінюється без зміни адреси.
  • Не вимірюйте успіх лише часткою відповідей із кешу. Перевіряйте навантаження, помилки, свіжість і відсутність витоку персоналізації.

Джерела

Короткий чеклист

  • вибрати один публічний контрольний URL
  • зберегти заголовки двох послідовних відповідей
  • перевірити журнали запитів до сервера-джерела
  • класифікувати маршрут до зміни правил
  • протестувати анонімні, авторизовані та варіантні запити
  • визначити метрики й умови відкату

Знайти причину, через яку CDN не кешує відповідь

Допоможи дослідити, чому конкретний URL не залишається в кеші CDN. Спочатку попроси такі вхідні дані: - URL або шаблон шляху без секретних параметрів; - очікуваний тип контенту та спосіб його оновлення; - чи залежить відповідь від користувача, заголовків `Cookie` або `Authorization`; - заголовки двох послідовних відповідей; - заголовки `Cache-Control`, `Set-Cookie`, `Vary`, `ETag`, `Last-Modified`, `Age` і стану кешу CDN, якщо вони доступні; - відповідні записи журналу сервера-джерела; - доступні метрики й обмеження на зміну застосунку або CDN. Не пропонуй примусове кешування, доки не визначиш, чи відповідь однакова для всіх, залежить від безпечної ознаки варіанта (наприклад, мови або регіону) чи містить персональні дані. Позначай припущення та відсутні дані. Поверни результат у форматі: 1. Короткий висновок. 2. Таблиця доказів: спостереження, значення, практичний наслідок. 3. Найімовірніша причина та альтернативні причини. 4. Основне виправлення на сервері-джерелі з точними кандидатами заголовків. 5. Вузьке тимчасове правило на CDN, якщо сервер-джерело зараз змінити не можна. 6. План канаркового впровадження, метрики успіху та умови відкату. 7. Перевірки, що запобігають кешуванню персоналізованих відповідей.