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

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

Обзор

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

 

Обзор

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

Обзор - 2

 

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

Браузер является основным потребителем заголовков HTTP- кэша. Но эти заголовки доступны для каждого промежуточного прокси-сервера, а также для кэша между исходным сервером и конечным пользователем.

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

Есть два основных заголовка кэша: Cache-Control и Expires.

Cache-Control

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

Значение public - ресурсы могут кэшироваться не только браузером, но и промежуточными прокси-серверами, которые могут обслуживать других пользователей.

Cache-Control:public

private - ресурсы пропускаются промежуточными прокси-серверами и могут быть кэшированы только конечным клиентом.

Cache-Control:private

Значение заголовка Cache-Control является составным. Оно указывает, является ли ресурс общедоступным или приватным. Также в нем прописано максимальное время, в течение которого он может храниться. Значение max-age задает отрезок (в секундах) времени, определяющий, как долго должен кэшироваться ресурс.

Cache-Control:public, max-age=31536000

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

Expires

При использовании вместе с Cache-Control заголовок Expires задает дату, начиная с которой кэшированный ресурс считается устаревшим. После этой даты браузер будет запрашивать новую копию ресурса. До этого момента будет использоваться сохраненная версия:

Если установлены Expires и max-age, значение  max-age будет иметь приоритет.

Cache-Control:public
Expires: Mon, 25 Jun 2012 21:31:12 GMT

Несколько других заголовков указывают, как извлекать ресурсы из Сети. Этот тип запросов известен как условные запросы.

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

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

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

Но если ресурс неизменен, тело ответа будет пустым. Это снижает объем данных при передаче ресурса обратно клиенту.

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

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

Чтобы включить условные запросы, приложение указывает время последнего изменения ресурса через заголовок ответа Last-Modified.

Cache-Control:public, max-age=31536000
Last-Modified: Mon, 03 Jan 2011 17:45:57 GMT

В следующий раз браузер запросит ресурс через заголовок запроса If-Modified-Since, только если оно изменилось с этой даты.

If-Modified-Since: Mon, 03 Jan 2011 17:45:57 GMT

Если ресурс не изменился с Mon, 03 Jan 2011 17:45:57 GMT, сервер вернет ответ с пустым телом и кодом ответа 304.

Условные запросы на основе содержимого

ETag (или Entity Tag) работает аналогично заголовку Last-Modified. Его значения являются кратким описанием содержимого ресурсов (например, хешем MD5). Это позволяет серверу определить, отличается ли сохраненный ресурс от самой последней версии.

Этот тег полезен, когда трудно определить дату последнего изменения.

Cache-Control:public, max-age=31536000
ETag: "15f0fff99ed5aae4edffdd6496d7131f"

При последующих запросах браузера заголовок запроса  If-None-Match  отправляется со значением ETag с последней запрошенной версией ресурса.

If-None-Match: "15f0fff99ed5aae4edffdd6496d7131f"

Если текущая версия имеет значение ETag, указывающее, что оно совпадает с кэшированной копией в браузере, то возвращается HTTP-статус 304.

Видимость

Большинство современных браузеров включают в себя средства визуализации запросов и ответов. Веб-инспектор в браузерах Google Chrome и Safari показывает заголовки ответа и запроса на вкладке «Сеть».

Код примера приложения, использующего различные заголовки кэша, можно найти на GitHub. Само приложение доступно по адресу http://http-caching-demo.herokuapp.com/ .

Первоначальный запрос к http://http-caching-demo.herokuapp.com/ отобразит набор заголовков, возвращаемых приложением по умолчанию (без директив кэша).

Видимость

После добавления параметра cached приложение http://http-caching-demo.herokuapp.com/?cache=true включает кэширование с заголовками Cache-Control и Expires . Для обоих в будущем будет установлено значение 30 секунд.

Видимость - 2

После добавления параметра запроса etag приложение http://http-caching-demo.herokuapp.com/?etag=true вернет короткое описание содержимого JSON ETag.

При более глубокой проверке условный запрос на основе ETag выполняется, как и ожидалось. При первоначальном запросе браузер фиксирует загрузку файла с сервера:

Но при последующих запросах сервер отвечает на ETag браузера HTTP-статусом 304 (не изменен). Это указывает браузеру использовать сохраненную копию:

 

Когда применять

Статические ресурсы

В веб-приложении чаще всего кэшируются файлы, которые не изменяются: изображения, CSS и Javascript. Эти используются на каждой странице. Поэтому кэширование позволит улучшить производительность приложения.

Для этого нужно использовать заголовок Cache-Control с максимальным значением в 1 год. Рекомендуется установить для заголовка Expires аналогичное значение.

1 год составляет 31536000 секунд

Cache-Control:public; max-age=31536000
Expires: Mon, 25 Jun 2013 21:31:12 GMT

RFC не поддерживает большие периоды времени, и они могут игнорироваться.

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

В случае с динамическим контентом существует намного больше нюансов. В качестве двух простых примеров можно привести содержимое RSS-канала блога (который будет обновляться не чаще одного раза в несколько часов). А также пакеты JSON, управляющие лентой пользователя Twitter (обновляемой каждые несколько секунд). В этих случаях разумно кэшировать ресурсы надолго, но чтобы это не привело к проблемам для конечного пользователя.

Приватный контент

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

Если кэширование необходимо, вы можете запросить кэширование ресурсов только в приватном порядке (только в кэше браузера):

Cache-Control:private, max-age=31536000

Запрет кэширования

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

В дополнение к значениям public и private для заголовка Cache-Control можно задать значения no-store  и no-cache. Они указывают браузеру не кэшировать ресурсы при любых обстоятельствах.

Оба значения обязательны, так как IE использует no-cache, а Firefox - no-store.

Cache-Control:no-cache, no-store

Реализация

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

Пожалуйста, опубликуйте свои комментарии по текущей теме материала. Мы крайне благодарны вам за ваши комментарии, дизлайки, отклики, лайки, подписки!