MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

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

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

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

{{HTTPSidebar}}

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

 

Различные виды кэширования

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

Существует несколько видов кешей, которые можно разделить на две основные категории: приватные кеши и кеши совместного использования. В кешах совместного использования (shared cache) хранятся копии, которые могут направляться разным пользователями. Приватный кеш (private cache) предназначен для отдельного пользователя. Здесь будет говориться в основном о кешах браузеров и прокси, но существуют также кеши шлюзов, CND, реверсные прокси кеши и балансировщики нагрузки, разворачиваемые на серверах для повышения надежности, производительности и масштабируемости веб-сайтов и веб-приложений.

 

What a cache provide, advantages/disadvantages of shared/private caches.

Приватный (private) кэш браузера

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

Общий (shared) прокси-кэш

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

Цели кэширования

Кеширование в HTTP не является обязательным, однако в большинстве случаев бывает полезно повторно использовать ранее сохраненных ресурсов. Тем не менее, стандартные кеши HTTP обычно способны кешировать только отклики метода {{HTTPMethod("GET")}} , а другие отклоняют.

Первичный ключ состоит из метода запроса и запрашивемого URI (зачастую используется только URI, поскольку целью кеширования являются только запросы метода GET ). Вот примеры того, что обычно записывается в кеш:

  • Сообщение об успехе запроса: отклик {{HTTPStatus(200)}} (OK) на запрос методом {HTTPMethod("GET")}} HTML-документов, изображений или файлов.
  • Постоянная переадресация: отклик {{HTTP Status (301)}} (Moved Permanently - Перемещен).
  • Сообщение об ошибке: страница {{HTTPStatus(404)}} (Not Found - Не найдено).
  • Сообщение, что результат не полон: отклик {{HTTPStatus(206)}} (Partial Content - Часть содержимого).
  • Отклики методов, отличных от {{HTTPMethod("GET")}}, если есть что-либо, подходящее для использования в качестве ключа кеша.

Запись в кеше может также состоять из множества откликов, различаемых по вторичному ключу, если целью запроса является согласование данных. Подробнее об этом рассказано ниже, в разделе, посвященному заголовку {{HTTPHeader("Vary")}}.

Управление кэшированием

Заголовок Cache-control

Поле {{HTTPHeader("Cache-Control")}} общего заголовка HTTP/1.1 используется для задания инструкций по механизму кеширования как в запросах, так и в ответах. Применяется для задания политик кеширования.

Полное отсутствие кеширования

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

Cache-Control: no-store
Cache-Control: no-cache, no-store, must-revalidate

Не кешировать

Перед тем, как выдать копию, кеш запрашивает исходный сервер на предмет актуальности ресурса.

Cache-Control: no-cache

Приватные (private) и общие (public) кеши

Директива "public" указывает, что ответ можно сохранять в любом кеше. Это бывает полезно, если возникает потребность сохранить страницы с аутентификационной информацией HTTP или кодами статуса, которые обычно не кешируются. Директива же "private" указывает, что ответ предназначен отдельному пользователю и не должен, таким образом, храниться в кеше совместного использования. В этом случае ответ может  сохраняться приватным кешем браузера.

Cache-Control: private
Cache-Control: public

Срок действия (Expiration)

Самой важной является директива "max-age=<seconds>" - максимальное время, в течение которого ресурс  считается "свежим". В отличие от директивы {{HTTPHeader("Expires")}}, она привязана к моменту запроса. Для тех файлов, которые не должны меняться, можно использовать "агрессивное" кеширование. Сюда входят статичные файлы, такие как изображения, файлы стилей (CSS) или скриптов (JavaScript).

Подробнее об этом рассказывается в разделе Свежесть ресурса.

Cache-Control: max-age=31536000

Проверка актуальности

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

Cache-Control: must-revalidate

Заголовок Pragma

{{HTTPHeader("Pragma")}} является заголовком HTTP/1.0. Он не задан для ответов HTTP,  таким образом, не может служить надежной заменой заголовку "Cache-Control: no-cache" протокола HTTP/1.1 Cache-Control, хотя и ведет себя аналогичным образом когда поле заголовка Cache-Control опущено в запросе. Использовать его следует только для совместимости с клиентами HTTP/1.0.

Свежесть сохраненной копии

Однажды попав в кеш, ресурс, теоретически, может храниться там вечно. Однако, поскольку объем хранилища конечен, записи периодически приходится оттуда удалять.  Этот процесс называют вытеснением данных из кеша (cache eviction). Кроме того, на сервере ресурсы могут изменяться, поэтому кеш требуется обновлять. Поскольку HTTP является клиент-серверным протоколом, сервера не могут сами обращаться к кешам и клиентам при изменении ресурса; им необходимо договориться о сроке действия  сохраненной копии. До его истечения ресурс считается свежим (fresh), после - устаревшим (stale). Алгоритмы вытеснения отдают предпочтение "свежим" ресурсам. Тем не менее, копия ресурса не удаляется из кеша сразу же по истечению ее срока действия. При получении запроса на соответствующий ресурс кеш предваряет его с заголовком {{HTTPHeader("If-None-Match")}} на случай, если его копия все еще актуальна. Если это так, сервер возвращает заголовок {{HTTPStatus("304")}} (Not Modified - Не изменен), а тело ресурса не посылает, экономя тем самым траффик.

Вот пример того, как протекает этот процесс при использовании совместного кеша прокси:

 

Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale.

Время устаревания (freshnessLifetime) вычисляется на основании нескольких заголовков. Если задан заголовок "Cache-control: max-age=N", то время устаревания равно N. Если его нет, а это бывает очень часто, проверяется заголовок {{HTTPHeader("Expires")}}, и, если он есть, то время устаревания берется равным значению заголовка Expires минус значение заголовка Date. Наконец, если нет ни того ни другого, смотрят заголовок Last-Modified.  Если он есть, то время устаревания равно значению заголовка Date минус значение заголовка Last-modified разделить на 10.
Срок действия вычисляется следующим образом:

expirationTime (срок действия) = responseTime + freshnessLifetime - currentAge (текущий возраст)

где responseTime - это время получения ответа по часам браузера.

Обновление статичных ресурсов (Revved resources)

Чем больше ресурсов кешируется, тем быстрее сайт реагирует на запросы и тем выше его производительность. Из этих соображений их "срок годности" имеет смысл делать как можно большим. Однако, возникает проблема с ресурсами, которые обновляются редко и нерегулярно. Их выгоднее всего кешировать, но трудно обновлять. Такие ресурсы можно найти в любой веб-странице:  файлы скриптов (JavaScript) и стилей (CSS) изменяются редко, но уж если это произошло, обновление надо произвести как можно быстрее.

Веб разработчики разработали метод, который Стив Сандерс (Steve Sounders) назвал оборачиваемостью (revving[1]).

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

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

 

Номер версии, добавляемый к статическому ресурсу, не обязательно записывать в виде стандартного номера версии наподобие 1.1.3, или даже в порядке возрастания. Это может быть что угодно, позволяющее избежеть совпадений - например, дата.

Валидация кеша

Валидация кеша запускается при нажатии пользователем кнопки перезагрузки. Кроме того, она может выполняться в ходе обычного режима просмотра, если кешированный ответ включает заголовок "Cache-control: must-revalidate". Другим фактором являются настройки кеширования (окно  Advanced->Cache preferences) - можно потребовать принудительной валидации при каждой загрузке документа.

При истечении срока годности документа он либо проходит валидацию, либо повторно доставляется с сервера. Валидация может выполняться только если у сервера есть сильный валидатор или слабый валидатор.

 

Заголовки ETag

 

Заголовок ответа {{HTTPHeader("ETag")}} является непрозрачным для агента пользователя значением, которое можно использовать в качестве сильного валидатора. Агент пользователя, например, браузер, не знает, что представляет эта строка и не может предсказать, каким будет ее значение. Если заголовок ETag был частью ответа, клиент может вывести If-None-Match в заголовок будущих запросов для валидации кешированных ресурсов.

Заголовок ответа {{HTTPHeader("Last-Modified")}} можно использовать в качестве слабого валидатора. Слабым он считается из-за того, что имеет 1-секундное разрешение. Если в ответе присутствует заголовок Last-Modified, то для валидации кешированного документа клиент может выводить в запросах заголовок  {{HTTPHeader("If-Modified-Since")}}.

При запросе на валидацию сервер может либо проигнорировать его и послать стандартный ответ {{HTTPStatus(200)}} OK, либо вернуть ответ {{HTTPStatus(304)}} Not Modified (с пустым телом), указывая, таким образом, чтобы браузер взял копию из кеша. В последнем случае в ответ могут входить также заголовки для обновления срока действия кешированного ресурса.

Изменяющиеся ответы

Заголовок HTTP-ответов {{HTTPHeader("Vary")}} определяет, как по заголовкам будущих ответов понять, что вместо ресурса с исходного сервера следует взять копию из кеша.

Если кеш получает запрос, который можно удовлетворить сохраненным в кеше ответом с заголовком Vary, то использовать этот ответ можно только при совпадении всех полей заголовка, названных заголовком Vary, в исходном (сохраненном в кеше) запроса и новом запросе.

The Vary header leads cache to use more HTTP headers as key for the cache.

Это может быть полезно, например, при динамическом обслуживании контента. При использовании заколовка Vary: User-Agent header кеширующие сервера, принимая решение о том, использовать ли страницу из кеша, дожны учитывать агент пользователя. Так можно избежать ситуации, когда пользователи мобильных устройств по ошибке получат десктоповую версию вашего сайта. Кроме того, это может помочь Google и другим поисковым системам обнаружить версию страницы, предназначенную для мобильных устройств, и, возможно, подскажет им, что не предполагается никакой маскировки (Cloaking).

Vary: User-Agent

Посколько значение заголовка {{HTTPHeader("User-Agent")}} различается ("varies") у мобильных и десктоповых клиентов, кеши не станут по ошибке отсылать мобильные версии для десктоповых клиентов, и наоборот.

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: mgalkina, koks
 Обновлялась последний раз: mgalkina,