Открыть сервис

Кэширование HTTP

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

Принцип работы

Кэширование HTTP основывается на правилах, определяемых заголовками запросов и ответов. Когда клиент впервые запрашивает ресурс, сервер может указать, можно ли кэшировать этот ответ и на какой срок. При повторном запросе того же ресурса клиент или промежуточный кэш проверяет, не истёк ли срок хранения копии. Если копия актуальна, она возвращается без обращения к серверу. Если срок истёк, клиент может отправить условный запрос, чтобы проверить, изменился ли ресурс на сервере. Если изменений нет, сервер отвечает статусом 304 Not Modified, и кэш продолжает использовать старую копию.

Типы кэшей

Браузерный кэш

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

Прокси-кэш

Прокси-кэш — это промежуточный сервер, который хранит копии ответов для множества пользователей. Такие кэши часто используются в корпоративных сетях, интернет-провайдерами или в сетях доставки контента (CDN). Прокси-кэш может обслуживать запросы от разных клиентов, снижая нагрузку на внешние каналы связи.

Кэш шлюза (обратный прокси)

Обратный прокси-сервер, расположенный перед веб-сервером, может кэшировать ответы от сервера и отдавать их клиентам. Это распространённая практика для снижения нагрузки на серверы приложений и ускорения ответа. Примеры: Nginx, Varnish, Apache Traffic Server.

Заголовки кэширования

Управление кэшированием осуществляется через HTTP-заголовки, которые сервер включает в ответ. Основные заголовки:

Cache-Control

Этот заголовок является основным современным механизмом управления кэшированием. Он может содержать несколько директив, разделённых запятыми:

  • public — ответ может кэшироваться любым кэшем (браузером, прокси).
  • private — ответ предназначен только для одного пользователя и не должен кэшироваться общими кэшами (например, личные данные).
  • no-cache — кэш должен проверять актуальность ответа на сервере перед использованием. При этом сам ответ может быть сохранён.
  • no-store — ответ нельзя сохранять в кэше ни при каких условиях.
  • max-age=<секунды> — максимальное время в секундах, в течение которого ответ считается свежим.
  • s-maxage=<секунды> — аналогично max-age, но только для общих кэшей (прокси).
  • must-revalidate — при истечении срока свежести кэш обязан обратиться к серверу для проверки.
  • immutable — указывает, что ресурс не изменится в течение времени его жизни (используется для статических файлов с хешами в именах).

Expires

Устаревший заголовок, содержащий абсолютную дату и время, после которых ответ считается устаревшим. Пример: Expires: Thu, 01 Dec 2025 16:00:00 GMT. В современных системах предпочтительнее использовать Cache-Control: max-age.

ETag

Заголовок ответа, содержащий уникальный идентификатор версии ресурса (например, хеш содержимого). При условном запросе клиент отправляет этот идентификатор в заголовке If-None-Match. Если ресурс не изменился, сервер отвечает 304 Not Modified.

Last-Modified

Заголовок ответа, указывающий дату и время последнего изменения ресурса. При условном запросе клиент отправляет это значение в заголовке If-Modified-Since. Если с указанной даты изменений не было, сервер отвечает 304 Not Modified.

Vary

Заголовок, указывающий, что кэш должен учитывать определённые заголовки запроса при определении уникальности ответа. Например, Vary: Accept-Encoding означает, что кэш должен хранить разные версии ответа для сжатого и несжатого контента.

Стратегии кэширования

Свежесть и устаревание

Ответ считается свежим, если его возраст не превышает указанное в max-age или Expires время. Если срок истёк, ответ считается устаревшим. Кэш может использовать устаревший ответ, если сервер недоступен, но это обычно настраивается отдельно.

Условные запросы

Когда кэш имеет устаревшую копию, он может отправить условный запрос с заголовками If-Modified-Since или If-None-Match. Если ресурс не изменился, сервер возвращает 304 Not Modified без тела ответа, экономя трафик. Если ресурс изменился, сервер возвращает полный ответ с кодом 200 OK.

Инвалидация кэша

При изменении данных на сервере (например, обновление статьи) необходимо инвалидировать соответствующие кэшированные копии. Это может быть сделано:

  • Изменением URL ресурса (например, добавление версии в путь: /style.v2.css).
  • Использованием заголовка Cache-Control: no-cache для динамических страниц.
  • Принудительной очисткой кэша на стороне сервера (например, через API CDN).

Кэширование в CDN

Сети доставки контента (CDN) активно используют кэширование для ускорения загрузки статических ресурсов (изображения, видео, скрипты, стили). CDN-серверы, расположенные в разных географических точках, кэшируют ответы от исходного сервера и отдают их ближайшим пользователям. Это снижает задержки и нагрузку на основной сервер. Управление кэшированием в CDN обычно осуществляется через заголовки Cache-Control и Expires, а также через собственные настройки панели управления CDN.

Проблемы и ограничения

Динамический контент

Кэширование динамического контента (например, персональных страниц пользователя, корзины покупок) затруднено, так как ответ зависит от конкретного запроса. Для таких случаев применяются заголовки private или no-cache.

Кэш-инвалидация

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

Размер кэша

Браузеры и прокси-серверы имеют ограничения на размер кэша. При превышении лимита старые записи удаляются (вытесняются) по алгоритму, обычно LRU (Least Recently Used — наименее недавно использовавшийся).

Безопасность

Конфиденциальные данные (например, номера кредитных карт, токены авторизации) не должны кэшироваться. Для этого используется директива no-store. Также следует учитывать, что кэш может быть атакован (например, кэш-отравление), если злоумышленник сможет подменить содержимое кэша.

Примеры использования

  • Статические ресурсы: изображения, CSS-файлы, JavaScript-файлы, шрифты. Для них обычно устанавливается большое max-age (например, год) и используется immutable, если имя файла содержит хеш.
  • API-ответы: для данных, которые редко меняются (например, список стран), можно установить max-age на несколько минут или часов. Для часто меняющихся данных (например, курс валют) — no-cache или короткое max-age.
  • HTML-страницы: для новостных сайтов или блогов можно кэшировать страницы на несколько минут, чтобы снизить нагрузку на сервер. Для персональных страниц (личный кабинет) — private, no-cache.

Интересные факты

  • HTTP-кэширование является одним из ключевых механизмов, обеспечивающих работу современного интернета, позволяя снижать нагрузку на серверы в десятки и сотни раз.
  • Протокол HTTP/2 и HTTP/3 не меняют принципов кэширования, но могут улучшить производительность за счёт мультиплексирования и сжатия заголовков.
  • В некоторых браузерах (например, Google Chrome) есть встроенные инструменты для просмотра и очистки кэша, а также для отладки кэширования через панель разработчика.

Источники

  • RFC 7234 — Hypertext Transfer Protocol (HTTP/1.1): Caching
  • RFC 5861 — HTTP Cache-Control Extensions for Stale Content
  • Документация MDN Web Docs: HTTP caching
  • Книга «HTTP: The Definitive Guide» by David Gourley, Brian Totty
  • Документация Nginx: модуль ngx_http_proxy_module

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →