Pull to refresh

Гид по заголовкам кэширования HTTP для начинающих

Reading time 8 min
Views 82K
Original author: Kyle Young
В статье данные сведения по заголовкам кэширования (ЗК) для HTTP и соответствующее поведение сетей доставки контента (CDN). Если вам хочется разобраться, каким образом заголовки кэширования вписываются в современный веб, или вам просто интересно, о чём говорят ваши коллеги – эта статья для вас.

Если вы уже понимаете преимущества ЗК, и хотите расширить свои знания, я рекомендую вам обратиться к документации от W3.

Что могут ЗК сделать для вас?


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

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

В случае ресурсов вроде логотипа вашей компании, favicon сайта или основных CSS-файлов, которые не меняются от запроса к запросу, можно разрешить запрашивающему хранить копии этих файлов какое-то время. Если бы ваши посетители были детьми на заднем сиденье автомобиля, которые бы всё время спрашивали вас «Мы уже приехали?», то это разрешение было бы сродни ответу «Нет, и нам ехать ещё 20 минут, так что запомните мой ответ».

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

Для клиентов и CDN


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

Что такое CDN?

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


При правильной настройке, CDN передаёт ваш контент клиентам через самый быстрый и ближайший к нему сервер. Кроме этого, CDN работает буфером между вами и пользователями. Нас интересует процент количества кэшированных запросов – тех запросов, которые CDN обработало, не дёргая наш сервер. В зависимости от трафика и архитектуры этот номер может достигать и 90%, хотя эффект вы заметите и при меньших цифрах. Надо заметить, что при небольшом количестве запросов большая их часть будет отправляться на ваш сервер – поэтому этот процент имеет смысл только вместе с временем кэширования и общей нагрузкой сайта. Но если вы настроите один лишь кэш, а заголовки кэширования будут работать неправильно, итоговые показатели могут даже стать хуже, чем были.

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

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

Основные заголовки


1. cache-control

Самый главный из всех. Обычно вы задаёте в строке его параметры, нечто вроде:

cache-control: private, max-age=0, no-cache

Эти настройки называются директивы ответа кэша, и они бывают следующие:

private | public

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

no-cache

Сама по себе директива говорит, что этот запрос нужно каждый раз делать заново. Обычно используется заголовок etag, о котором ниже. Веселье начинается, когда вы задаёте имя поля после этой директивы. Тогда кэширующие сервера понимают, что ответ можно кешировать, но при этом надо удалять заданные поля. Это, например, полезно для правильной работы куков. Однако, некоторые старые программы не умеют работать с этим трюком.

no-store

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

max-age

Обычно время жизни ресурса задаётся через expires, но если вам надо быть более конкретным, можно задать max-age в секундах. И эта директива имеет преимущество над expires.

s-maxage

Немного похоже на предыдущую, однако s здесь означает shared cache, и нужна для CDN. Эта директива имеет преимущество над max-age и expires, когда речь идёт о CDN-серверах.

must-revalidate

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

no-transform

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

proxy-revalidate

Примерно то же, что must-revalidate, но для промежуточных CDN-серверов. Почему её не назвали s-mustrevalidate? Кто его знает. Смысл в том, что проверять, не обновился ли контент, нужно для каждого нового пользователя только один раз.

2. expires

Изначально это был стандартный метод определения того, когда устаревает ресурс. Сегодня max-age и s-maxage имеют над ним преимущество, но всегда полезно задавать этот заголовок в целях обратной совместимости.

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

3. etag

Сокращение от entity-tag. Это уникальный идентификатор запрашиваемого ресурса – обычно, некий хэш его содержимого, или хэш времени его обновления. В общем, способ клиента запросить у CDN «дай мне ресурс Х, если у него etag отличается от моего».

4. vary

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

Часто можно встретить заголовок типа Accept-Encoding, который удостоверяется, что ваши ресурсы, сжатые gzip, будут приняты клиентом. Это здорово сберегает трафик. Кроме этого, настройка

vary: User-Agent

сделает ваш сайт более дружественным к SEO, если вы раздаёте разные HTML/CSS в зависимости от User-Agent. Google заметит эту штучку и Googlebot будет обрабатывать и ваш мобильный контент.

5. pragma

Довольно старая директива, которая умеет делать много чего, что, однако, уже обрабатывается при помощи более современных. Нам более всего интересна форма

pragma: no-cache

что в современных клиентах превращается в

cache-control: no-cache

Предостережения


Не все CDN или программы у клиентов работают согласно спецификациям. Если вы занимаетесь веб-разработкой, вам знакома эта проблема. Поэтому перед запуском сервиса всегда надо тестировать его, чтобы убедиться, что всё работает, как нужно.

Кроме того, вы могли заметить, что некоторые заголовки дублируют друг друга или их области применения перекрываются. Это происходит из-за небольших различий у разных методов, или из-за перехода веба с HTTP/1.0 на протокол HTTP/1.1, в котором кэширование расписано более подробно.

1. Сжатие

Провайдеры CDN, получающие запрос в gzip в качестве приемлемого сжатия, также должны запрашивать сжатый контент с сервера, или предоставлять клиенту сжатую версию ресурса. Современные CDN умеют проводить сжатие ресурсов самостоятельно.

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

2. SSL

CDN – это человек-в-середине. Вам нужно подумать об организации HTTPS-трафика и о том, как он идёт к вам на сервер. Многие CDN перенаправят запрос к somesite.com/asset на адрес somesite.com/asset, поэтому если логика вашего сервера зависит от протокола, либо поменяйте логику, либо попросите CDN сделать переадресацию на HTTPS.

А что же с динамическим контентом?


Обычно в этом случае надо задавать cache-control: no-cache, чтобы CDN не кэшировали его. Если вам интересно, как можно немного ускорить и его работу, продолжайте чтение.

Типичный динамический контент

HTTP/1.1 200 OK
Server: Apache
X-Rack-Cache: miss
ETag: "e6811cdbcedf972c5e8105a89f637d39-gzip"
Status: 200
Content-Type: text/html; charset=utf-8
Expires: Mon, 29 Apr 2013 21:44:55 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Mon, 29 Apr 2013 21:44:55 GMT


Большая часть динамического контента не такая уж и непостоянная. Список активных пользователей, к примеру, имеет время жизни 10-20 секунд. Страницы с графиками наверняка могут пожить несколько минут. Новостная лента может некоторое время и покэшироваться, особенно при наличии etag. Если загрузка вашего сайта велика, стоит попробовать кэшировать ненадолго некоторые его ресурсу

Анализ времени кэширования


Так какое время для хранения ресурсов лучше задавать? Это зависит от количества трафика, размера ресурсов, размера кэша.

Кроме того, надо подумать о главном недостатке кэширования – уменьшении контроля над ресурсами. Если вам надо обновить ресурс мгновенно, у вас будут проблемы, если вы некоторое время назад задали ему время жизни в год. Особенно, если вы задали это время не только для CDN (s-maxage), но и для пользователей (max-age).

Самый длительный промежуток для кэша – год, или 31536000. Но это плохая идея. Это всё равно, что сделать татуировку на лице. Если ваши сервера не выдерживают хотя бы ежедневных запросов от CDN по поводу того, изменился ли ресурс,- пора менять сервера.

Заголовки для статичного контента

HTTP/1.1 200 OK
Cache-Control: no-transform,public,max-age=300,s-maxage=900
Content-Type: text/html; charset=UTF-8
Date: Mon, 29 Apr 2013 16:38:15 GMT
ETag: "bbea5db7e1785119a7f94fdd504c546e"
Last-Modified: Sat, 27 Apr 2013 00:44:54 GMT
Server: AmazonS3
Vary: Accept-Encoding
X-Cache: HIT


Пример настроек кэша для статичного контента с S3. Кэшу рекомендуется хранить ресурс 900 секунд, пользовательским программам – 300 секунд. Последний заголовок говорит о том, какой из CDN обработал запрос.

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

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

Время кэширования (мин) Процент запросов к кэшу Запросов к оригиналу в час
1 99.8% 60
5 99.96% 12
20 99.99% 3
60 99.997% 1
86400 99.9998% <1


Какой процент запросов к кэшу вас устроит? Обычно от 60 секунд до 60 минут – нормальное время жизни для ресурса. Для псевдо-динамического контента можно устанавливать время кэширования в промежутке до 60 секунд.

Проверка CDN


Проверяйте, что заголовки проходят через CDN так, как вы этого ожидаете. Обычно CDN вставляет какой-нибудь Х- заголовок, где указывает подробности по данному ресурсу. Вот некоторые инструменты, которые показались мне довольно полезными.

1. Web Inspector

Самый простой метод – правый клик на странице в Chrome, выбрать Inspect Element, перейти на закладку Network и нажать на ресурс HTML. Если это не выбрано по умолчанию, выбрать закладку Headers, чтобы посмотреть все заголовки. Также в Chrome есть возможности задать user agent и не использовать локальный кэш.

2. Charles Proxy

Через такой прокси можно перенаправить трафик и манипулировать запросами DNS, записывать заголовки, смотреть статистику быстродействия – всё это в понятном и простом GUI.

3. cURL

Делайте запросы из командной строки и просматривайте заголовки ответов. Полезные ключи: -A просмотр user anget, -b – куки, -F – данные форм, -H – назначить заголовки, -I – запрос только заголовков.

4. hurl.it

Грубо говоря, это cURL с понятным интерфейсом. Можно задавать заголовки и просматривать заголовки ответа и тело ответа.

5. Python и Requests

Requests – библиотека для Python для веб-запросов. С её помощью можно написать автоматизированные тесты для вашего сайта.

Заметки на полях


Теперь, когда вы прочли весь гид, немного замечаний.

Большинство веб-серверов, таких, как Apache и Nginx, делают большую часть работы за вас. Вам придётся работать только с заголовком cache-control. Браузеры обычно настроены на сильное кэширование контента, поэтому вам чаще приходится бороться с излишним кэшированием, нежели наоборот. Обычно вы задаёте некий путь вроде “/static”, который кэшируется какое-то разумное время, например, 300 секунд. Затем надо убедиться, что корневой путь "/" отдаётся с заголовком “cache-control: no-cache”, а лучше перенаправлять пользователя за динамическим контентом прямо на ваши сервера, и оставлять для CDN только то, что лежит в “/static”.

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

За дополнительными материалами по ускорению работы сайта рекомендуем обратиться к документации Mobile Web Performance.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+30
Comments 8
Comments Comments 8

Articles