Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.
Производительность веб-сайтов и приложений можно значительно повысить за счет повторного использования ранее собранных ресурсов. Кеши веб сокращают задержку и снижают сетевой траффик, уменьшая тем самым время, необходимое для отображения ресурсов. Используя HTTP-кеширование, сайты становятся более отзывчивыми.
Различные виды кэширования
Кеширование - этот метод, заключающийся в сохранении копии полученного ресурса, чтобы вернуть ее по запросу. Запрос на ресурс, уже имеющийся в веб-кеше, перехватывается, и вместо обращения к исходному серверу выполняется загрузка копии из кеша. Таким образом снижается нагрузка на сервер, которому не приходится самому обслуживать всех клиентов, и повышается производительность - кеш ближе к клиенту, и ресурс передается быстрее. Кеширование является основным источником повышения производительности веб-сайтов. Однако, кеш надо правильно сконфигурировать: ресурсы редко остаются неизменными, так что копию требуется хранить только до того момента, как ресурс изменился, но не дольше.
Существует несколько видов кешей, которые можно разделить на две основные категории: приватные кеши и кеши совместного использования. В кешах совместного использования (shared cache) хранятся копии, которые могут направляться разным пользователями. Приватный кеш (private cache) предназначен для отдельного пользователя. Здесь будет говориться в основном о кешах браузеров и прокси, но существуют также кеши шлюзов, CDN, реверсные прокси кеши и балансировщики нагрузки, разворачиваемые на серверах для повышения надежности, производительности и масштабируемости веб-сайтов и веб-приложений.
Приватный (private) кэш браузера
Приватный кеш предназначен для отдельного пользователя. Вы, возможно, уже видели параметры "кеширования" в настройках своего браузера. Кеш бразера содержит все документы, загруженные пользователем через HTTP. Он используется, чтобы можно было пролистывать назад/вперед загруженные ранее страницы, сохранять или использовать их в качестве ресурса, не обращаясь лишний раз к серверу. Кроме того, кеш полезен при отключении от сети.
Общий (shared) прокси-кэш
Кеш совместного использования - это кеш, который сохраняет отклики, чтобы их потом могли использовать разные пользователи. Прокси, обслуживающий множество пользователей, может установить, например, ваш провайдер или компания в своей локальной сети, чтобы можно было повторно использовать популярные ресурсы, сокращая тем самым сетевой траффик и время ожидания.
Цели кэширования
Кеширование в HTTP не является обязательным, однако в большинстве случаев бывает полезно повторно использовать ранее сохраненных ресурсов. Тем не менее, стандартные кеши HTTP обычно способны кешировать только отклики метода GET
, а другие отклоняют.
Первичный ключ состоит из метода запроса и запрашивемого URI (зачастую используется только URI, поскольку целью кеширования являются только запросы метода GET ). Вот примеры того, что обычно записывается в кеш:
- Сообщение об успехе запроса: отклик
200
(OK) на запрос методом {HTTPMethod("GET")}} HTML-документов, изображений или файлов. - Постоянная переадресация: отклик
301
(Moved Permanently - Перемещен). - Сообщение об ошибке: страница
404
(Not Found - Не найдено). - Сообщение, что результат не полон: отклик
206
(Partial Content - Часть содержимого). -
Отклики методов, отличных от
GET
, если есть что-либо, подходящее для использования в качестве ключа кеша.
Запись в кеше может также состоять из множества откликов, различаемых по вторичному ключу, если целью запроса является согласование данных. Подробнее об этом рассказано ниже, в разделе, посвященному заголовку Vary
.
Управление кэшированием
Заголовок Cache-control
Поле 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>" - максимальное время, в течение которого ресурс считается "свежим". В отличие от директивы Expires
, она привязана к моменту запроса. Для тех файлов, которые не должны меняться, можно использовать "агрессивное" кеширование. Сюда входят статичные файлы, такие как изображения, файлы стилей (CSS) или скриптов (JavaScript).
Подробнее об этом рассказывается в разделе Свежесть ресурса.
Cache-Control: max-age=31536000
Проверка актуальности
При использовании инструкции "must-revalidate" кеш обязан проверять статус ресурса с истекшим сроком действия. Те копии, что утратили актуальность, использоваться не должны. Подробнее об этом рассказано ниже, в соответствующем разделе
Cache-Control: must-revalidate
Заголовок Pragma
Pragma
является заголовком HTTP/1.0. Он не задан для ответов HTTP, таким образом, не может служить надежной заменой заголовку "Cache-Control: no-cache" протокола HTTP/1.1 Cache-Control, хотя и ведет себя аналогичным образом когда поле заголовка Cache-Control опущено в запросе. Использовать его следует только для совместимости с клиентами HTTP/1.0.
Свежесть сохраненной копии
Однажды попав в кеш, ресурс, теоретически, может храниться там вечно. Однако, поскольку объем хранилища конечен, записи периодически приходится оттуда удалять. Этот процесс называют вытеснением данных из кеша (cache eviction). Кроме того, на сервере ресурсы могут изменяться, поэтому кеш требуется обновлять. Поскольку HTTP является клиент-серверным протоколом, сервера не могут сами обращаться к кешам и клиентам при изменении ресурса; им необходимо договориться о сроке действия сохраненной копии. До его истечения ресурс считается свежим (fresh), после - устаревшим (stale). Алгоритмы вытеснения отдают предпочтение "свежим" ресурсам. Тем не менее, копия ресурса не удаляется из кеша сразу же по истечению ее срока действия. При получении запроса на соответствующий ресурс кеш предваряет его с заголовком If-None-Match
на случай, если его копия все еще актуальна. Если это так, сервер возвращает заголовок 304
(Not Modified - Не изменен), а тело ресурса не посылает, экономя тем самым траффик.
Вот пример того, как протекает этот процесс при использовании совместного кеша прокси:
Время устаревания (freshnessLifetime) вычисляется на основании нескольких заголовков. Если задан заголовок "Cache-control: max-age=N", то время устаревания равно N. Если его нет, а это бывает очень часто, проверяется заголовок 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
Заголовок ответа ETag
является непрозрачным для агента пользователя значением, которое можно использовать в качестве сильного валидатора. Агент пользователя, например, браузер, не знает, что представляет эта строка и не может предсказать, каким будет ее значение. Если заголовок ETag был частью ответа, клиент может вывести If-None-Match в заголовок будущих запросов для валидации кешированных ресурсов.
Заголовок ответа Last-Modified
можно использовать в качестве слабого валидатора. Слабым он считается из-за того, что имеет 1-секундное разрешение. Если в ответе присутствует заголовок Last-Modified, то для валидации кешированного документа клиент может выводить в запросах заголовок If-Modified-Since
.
При запросе на валидацию сервер может либо проигнорировать его и послать стандартный ответ 200
OK, либо вернуть ответ 304
Not Modified (с пустым телом), указывая, таким образом, чтобы браузер взял копию из кеша. В последнем случае в ответ могут входить также заголовки для обновления срока действия кешированного ресурса.
Изменяющиеся ответы
Заголовок HTTP-ответов Vary
определяет, как по заголовкам будущих ответов понять, что вместо ресурса с исходного сервера следует взять копию из кеша.
Если кеш получает запрос, который можно удовлетворить сохраненным в кеше ответом с заголовком Vary
, то использовать этот ответ можно только при совпадении всех полей заголовка, названных заголовком Vary
, в исходном (сохраненном в кеше) запроса и новом запросе.
Это может быть полезно, например, при динамическом обслуживании контента. При использовании заколовка Vary: User-Agent
header кеширующие сервера, принимая решение о том, использовать ли страницу из кеша, дожны учитывать агент пользователя. Так можно избежать ситуации, когда пользователи мобильных устройств по ошибке получат десктоповую версию вашего сайта. Кроме того, это может помочь Google и другим поисковым системам обнаружить версию страницы, предназначенную для мобильных устройств, и, возможно, подскажет им, что не предполагается никакой маскировки (Cloaking).
Vary: User-Agent
Посколько значение заголовка User-Agent
различается ("varies") у мобильных и десктоповых клиентов, кеши не станут по ошибке отсылать мобильные версии для десктоповых клиентов, и наоборот.
Смотрите также
- RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching
- Caching Tutorial – Mark Nottingham
- HTTP caching – Ilya Grigorik
- RedBot, инструмент для проверки относящихся к кешу заголовков HTTP .