Разумное кэширование контента – один из наиболее эффективных способов улучшить пользовательский опыт вашего сайта. Кэширование – это временное сохранение контента из предыдущих запросов. Кэширование является частью стратегии доставки основного контента, реализованной в протоколе HTTP. Компоненты на всем пути доставки могут кэшировать элементы для ускорения обработки последующих запросов с учетом объявленных политик.
В этой статье мы обсудим основные понятия из области кэширования веб-контента, а также поговорим о преимуществах, которые дает кеширование, о побочных эффектах и различных стратегиях для обеспечения наилучшего сочетания производительности и гибкости.
Что такое кэширование?
Кэширование – это способ оптимизации работы приложения, при котором повторно запрашиваемый контент сохраняется и используется для обслуживания последующих запросов. Существует множество различных типов кэширования, каждый из которых имеет свои плюсы и минусы. Кэш приложения и кэш памяти могут ускорять ответы на определенные запросы.
Кэширование веб-приложения, которому уделяется основное внимание в этой статье, является отдельным типом кэша. Веб-кэширование является основной конструктивной особенностью протокола HTTP, предназначенного для минимизации сетевого трафика и улучшения отзывчивости системы в целом. Контент кэшируется на каждом уровне от исходного сервера до браузера.
Веб-кеширование работает путем кэширования HTTP-ответов для запросов в соответствии с определенными правилами. Последующие запросы кэшированного контента затем можно извлечь из ближайшего кэша, а не отправлять запрос обратно на веб-сервер.
Преимущества кэширования
Эффективное кэширование помогает как пользователям, так и контент-провайдерам. Вот некоторые из преимуществ:
- Снижение сетевых затрат. Контент можно кэшировать в разных точках сетевого пути между потребителем и источником контента. Когда контент кэшируется ближе к потребителю, запросы не будут требовать значительной сетевой активности за пределами кэша.
- Повышение отзывчивости. Кэширование позволяет получать контент быстрее, потому что нет необходимости снова проделывать путь по всей сети. Кэши, поддерживаемые рядом с пользователем, например кэш браузера, могут сделать обслуживание запроса почти мгновенным.
- Повышенная производительность. Контент-провайдер может использовать мощные серверы в пути доставки, чтобы взять на себя основную нагрузку на обслуживание контента.
- Доступность контента во время сбоев сети. При использовании определенных политик кэширование может обслуживать контент пользователям даже в течение коротких сбоев.
Основные термины
Ниже приведены некоторые из наиболее распространенных терминов из области кэширования:
- Сервер-источник, или исходный сервер – это исходное местоположение контента. Для администратора веб-сервера это машина, которой он управляет. Этот сервер отвечает за обслуживание контента, который нельзя извлечь из кэша в маршруте запроса, и для настройки политики кэширования контента.
- Коэффициент попадания в кэш – это мера измерения продуктивности кэша. Это отношение количества запросов, которые можно обслужить из кэша, к общему количеству запросов. Высокий коэффициент попадания в кэш означает, что из кэша можно извлечь высокий процент контента. Обычно к такому результату стремится большинство администраторов.
- Свежесть кэша помогает понять, может ли элемент в кэше быть кандидатом на обслуживание клиенту. Контент в кэше будет использоваться для обслуживания запроса только в том случае, если он находится в пределах времени свежести, указанного политикой кэширования.
- Устаревший контент – это кэшированный контент, срок действия которого истек. Элементы в кэше устаревают в соответствии с параметрами свежести в политике кэширования. Устаревший контент нельзя использовать для обслуживания запросов клиентов. Нужно подключиться к исходному серверу, чтобы снова кэшировать этот контент или проверить его точность.
- Валидация – это проверка устаревшего контента на исходном сервере с целью уточнить последнюю версию элемента.
- Инвалидация – это процесс удаления контента из кэша раньше срока истечения его свежести. Это необходимо, если элемент был изменен на исходном сервере, а в кэше хранится его устаревший элемент, что вызовет значительные проблемы для клиента.
Что можно кэшировать?
Некоторый контент легче кэшировать. Для большинства сайтов кэшировать лучше:
- Логотипы и изображения бренда.
- Не ротируемые изображения в целом (например, значки навигации).
- Стили.
- Общие файлы Javascript.
- Загружаемый контент.
- Файлы мультимедиа.
Эти элементы меняются нечасто, поэтому их можно кэшировать в течение более длительных периодов времени.
А эти элементы нужно кэшировать осторожно:
- HTML-страницы.
- Ротируемые изображения.
- Часто изменяемые Javascript и CSS.
- Контент, запрашиваемый с помощью файлов cookie.
Кэшировать не рекомендуется:
- Активы, связанные с конфиденциальными данными. (банковская информация и т. д.)
- Контент, который зависит от пользователя и часто изменяется.
В дополнение к вышеуказанным общим правилам можно настроить политики, которые позволят вам соответствующим образом кэшировать различные типы контента. Например, если все авторизовавшиеся пользователи видят один и тот же вид сайта, может быть полезно кэшировать его. Если авторизовавшиеся пользователи видят пользовательский вид сайта, который будет действителен в течение некоторого времени, вы можете сохранить кэш в браузере пользователя, но исключить промежуточное кэширование.
Где хранится кэш?
Контент кэшируется в разные точки:
- Кэш браузера. Сами веб-браузеры поддерживают небольшой кэш. Как правило, браузер устанавливает политику, которая определяет наиболее важные элементы кэширования. Это может быть пользовательский контент или контент, который часто запрашивается и сложно извлекается.
- Прокси-серверы промежуточного кэширования. Любой сервер, находящийся между клиентом и вашей инфраструктурой, может кэшировать определенный контент. Эти кэши могут поддерживаться интернет-провайдерами или другими независимыми сторонами.
- Обратный кэш. Ваша серверная инфраструктура может реализовать собственный кэш для бэкэнд-сервисов. Таким образом, контент может обслуживаться из точки контакта, а бэкэнд-серверами.
Каждая из этих точек может поддерживать кэш в соответствии с собственными политиками кэширования и политикой кэширования контента.
Заголовки кэширования
Политика кэширования зависит от двух разных факторов. Сам объект кэширования принимает решение о том, следует ли кэшировать тот или иной контент. Он может решить кэшировать меньше, чем разрешено, но не сможет кэшировать больше контента.
Большая часть поведения при кэшировании определяется политикой, которую устанавливает владелец контента. Эти политики в основном формулируются с помощью HTTP-заголовков.
Благодаря различным версиям протокола HTTP появилось несколько разных заголовков кэширования с различными уровнями сложности. Вот основные:
- Expires очень простой. Он устанавливает время в будущем, когда истекает срок действия контента. На этом этапе любые запросы на контент будут возвращены на исходный сервер. Этот заголовок, вероятно, лучше всего использовать только как запасной.
- Cache-Control – современная замена Expires. Он хорошо поддерживается и реализует гораздо более гибкий дизайн. Почти во всех случаях он предпочтительнее Expires, но иногда может не помешать установить оба заголовка. Особенности параметров, которые вы можете установить с помощью Cache-Control, мы обсудим чуть позже.
- Заголовок Etag используется валидацией кэша. Сервер может предоставить уникальный Etag для элемента. Когда придет время проверить кэшированный контент, кэширующий сервер может отправить обратно Etag контента. Исходный сервер либо сообщит ему, что контент не изменился, либо отправит обновленный контент (с новым Etag).
- Last-Modified – этот заголовок указывает, когда элемент был изменен в последний раз. Он может использоваться как часть стратегии валидации для обеспечения свежего контента.
- Content-Length – этот заголовок имеет большое значение при определении политик кэширования. Некоторое программное обеспечение отказывается кэшировать контент, если оно заранее не знает о размере кэша.
- Vary – это заголовок, который сообщает системе, по каким заголовкам кэширования она может понять, что в кэше находится правильный контент. Чаще всего он используется для указания ключа заголовка Accept-Encoding, чтобы кэш мог различать сжатый и несжатый контент.
Немного о заголовке Vary
Заголовок Vary предоставляет вам возможность хранить разные версии одного и того же контента за счет разбавления записей в кэше.
В случае Accept-Encoding установка заголовка Vary позволяет провести критическое различие между сжатым и несжатым контентом. Это необходимо для правильного обслуживания этих элементов в браузерах, которые не могут обрабатывать сжатый контент, и для повышения юзабилити. Accept-Encoding хорошо подходит для Vary, потому что он имеет только два или три возможных значения.
Такие элементы, как User-Agent, на первый взгляд могут показаться хорошим способом разграничения между браузерами мобильных устройств и настольных компьютеров. Однако, поскольку строки User-Agent нестандартны, в результате может получиться множество версий одного и того же контента в промежуточных кэшах с очень низким коэффициентом попадания в кеш. Заголовок Vary следует использовать экономно, особенно если у вас нет возможности нормализовать запросы в промежуточных кэшах, которыми вы управляете (что может быть возможно, например, если вы используете сеть доставки контента).
Как флаги Cache-Control влияют на кэширование?
Выше упоминался заголовок Cache-Control, который используется для определения политики кэширования. С помощью этого заголовка можно установить несколько инструкций политики. Инструкции разделяются запятыми.
Вот некоторые из параметров Cache-Control, которые вы можете использовать для определения политики кэширования контента:
- no-cache: указывает, что любой кэшированный контент нужно повторно проверить на каждом запросе, прежде чем передавать клиенту. Это, по сути, сразу же помечает контент как устаревший, но позволяет использовать методы валидации, чтобы избежать повторной загрузки всего элемента.
- no-store: указывает, что содержимое не может быть кэшировано. Этот флаг уместно установить на конфиденциальные данные.
- public: указывает, что контент является общедоступным, что означает, что он может быть кэширован браузером и любыми промежуточными кэшами. Для запросов, использующих HTTP-аутентификацию, ответы по умолчанию помечены как private. Этот заголовок отменяет эту настройку.
- private: означает, что контент является конфиденциальным. Такой контент может храниться в браузере пользователя, но не должен кэшироваться промежуточными сторонами. Этот флаг часто используется для пользовательских данных.
- max-age: настраивает максимальный срок хранения кэшированного контента, прежде чем его нужно будет повторно загрузить с исходного сервера. По сути, он заменяет Expires и является основой для определения свежести контента. Этот параметр принимает значение в секундах; максимально допустимый срок свежести – 1 год (31536000 секунд).
- s-maxage: очень похож на max-age , поскольку указывает время, в течение которого можно хранить кэш. Разница в том, что этот параметр применяется только к промежуточным кэшам. Вместе с max-age он позволяет более гибко разрабатывать политику.
- must-revalidate: указывает на то, что информацию о свежести в max-age, s-maxage или Expires следует строго соблюдать. Нельзя обслуживать устаревший контент ни при каких обстоятельствах. Этот флаг предотвращает использование кэшированного контента в случае перебоев в сети и подобных сценариях.
- proxy-revalidate: работает так же, как и предыдущий, но применяется только к промежуточным прокси. В этом случае браузер пользователя можно использовать для обслуживания устаревшего контента в случае прерывания сети, но промежуточные кэши не могут использоваться для этой цели.
- no-transform: указывает кэшам, что при любых обстоятельствах им не разрешается изменять полученный контент по соображениям производительности. Это означает, например, что кэш не может отправлять сжатые версии содержимого, если он не получил их с исходного сервера.
Эти флаги можно по-разному комбинировать для достижения различного поведения в кэшировании. Но бывают и взаимоисключающие значения:
- no-cache и no-store
- public и private
Опция no-store переопределяет no-cache, если они обе присутствуют в политике. Для ответов на неавторизованные запросы используется public. Для ответов на аутентифицированные запросы применяется private. Их можно переопределить, включив в заголовок Cache-Control противоположную опцию.
Разработка стратегии кэширования
В идеальном мире все можно было бы кэшировать агрессивно, и серверы связывались бы только для проверки контента. Это не часто случается на практике, поэтому вы должны попытаться установить какие-то разумные требования в политике кэширования. Политика должна балансировать между реализацией долгосрочного кэширования и реагированием на требования меняющегося сайта.
Общие проблемы
Существует много ситуаций, когда кеширование невозможно или не должно реализовываться из-за того, как создается контент (динамически генерируемый контент для каждого пользователя), или из-за характера контента (например, это конфиденциальная банковская информация). Еще одна проблема, с которой сталкиваются многие администраторы при настройке кеширования, – это ситуация, когда более старые версии вашего контента находятся в кэше и еще не устарели, даже если уже появились новые версии.
Эти распространенные проблемы могут серьезно повлиять на производительность кэша и точность контента. Однако их можно смягчить, разработав политику кэширования с их учетом.
Общие рекомендации
Стратегия кэширования всегда зависит от ситуации, но следующие рекомендации могут помочь вам в принятии некоторых решений.
Есть несколько шагов, которые вы можете предпринять, чтобы увеличить коэффициент попадания в кэш, прежде чем обратиться к заголовкам.
- Установите определенные каталоги для изображений, css и общего контента. Размещение контента в выделенных каталогах позволит вам легко ссылаться на них с любой страницы вашего сайта.
- Используйте один и тот же URL-адрес для ссылки на одни и те же элементы. Поскольку кэш отталкивается как от хоста, так и от пути к запрошенному контенту, убедитесь, что вы ссылаетесь на свой контент на всех ваших страницах одинаково.
- Используйте CSS-спрайты, где это возможно. CSS-спрайты для элементов, таких как значки и навигация, уменьшают количество раундов, необходимых для рендеринга вашего сайта, и позволяют сайту кешировать этот единственный спрайт в течение длительного времени.
- По возможности храните сценарии и внешние ресурсы локально. Если вы используете скрипты javascript и другие внешние ресурсы, подумайте о том, чтобы разместить эти ресурсы на своих собственных серверах. Обратите внимание, что вам нужно знать о любых обновлениях, чтобы вовремя обновить локальную копию.
А вот справка по использованию общих заголовков кэширования:
- Разрешите всем кэшам хранить общие активы. Статический контент и контент, который не зависит от пользователя, могут и должны быть кэшированы во всех точках маршрута доставки контента. Это позволит промежуточным кэшам обслуживать контент для нескольких пользователей.
- Разрешите браузеру кэшировать пользовательские ресурсы. Кэширование в браузере пользователя часто бывает приемлемым и полезным решением. Этот контент не подходит для кэширования на промежуточных кеширующих прокси.
- Сделайте исключения для важного контента, сохраняющего ценность в течение определённого времени. Если у вас есть такой контент, сделайте исключение из приведенных выше правил, чтобы устаревший контент не обслуживался в критических ситуациях. Например, если на вашем сайте есть корзина для покупок, она должна немедленно отображать добавленные предметы. В зависимости от характера контента в заголовке Cache-Control можно задать параметры no-cache или no-store.
- Всегда используйте валидацию. Валидаторы позволяют обновлять устаревший контент без повторной загрузки всего ресурса. Установка заголовков Etag и Last-Modified позволяет кэшам проверять контент и повторно обслуживать его, если он не изменился (это еще больше снижает нагрузку).
- Установите срок свежести контента. Чтобы эффективно использовать кэширование, часто запрашиваемые элементы должны иметь длительный срок свежести. Обычно это касается таких элементов, как изображения и CSS, которые загружаются для отображения запрашиваемой страницы. Продолжительный срок свежести позволяет кэшу долго хранить эти ресурсы.
- Чтобы вышеприведенная схема заработала, содержащий элемент должен иметь относительно короткое время свежести или вообще не кэшироваться. Обычно это страницы HTML, которые вызывают другой вспомогательный контент. Сам HTML будет загружаться часто, что позволяет быстро реагировать на изменения. После этого поддерживающий контент можно кэшировать агрессивно.
Главной целью политики кэширования является достижение баланса, который позволяет применять агрессивное кэширование, когда это возможно, и оставляет возможность аннулировать записи при внесении изменений. Скорее всего, на каждом сайте будут:
- Агрессивно кэшируемые элементы.
- Элементы с коротким сроком свежести и необходимостью валидации.
- Элементы, которые не кэшируются вообще.
Цель состоит в том, чтобы по возможности перемещать контент в первые категории при сохранении приемлемого уровня точности.
Заключение
Потратив время на то, чтобы ваш сайт имел правильную политику кэширования, вы можете оказать значительное влияние на сайт. Кэширование позволяет сократить расходы, связанные с одновременным обслуживанием одного и того же контента.
Сервер также сможет обрабатывать большее количество трафика с помощью того же аппаратного обеспечения. Возможно, самое главное – кэширование может улучшить пользовательский опыт, благодаря чему посетители будут возвращаться на сайт. Конечно, эффективное кэширование – не волшебная палочка, но это может значительно повысить производительность.