HTTP-кэширование: ETag, Cache-Control и CDN
Почему ваш сайт работает медленно (и как кэширование это исправляет)
Вы оптимизировали изображения, минифицировали CSS и даже обновили сервер. Но повторные посетители всё ещё сталкиваются с медленной загрузкой, а ваш исходный сервер расходует пропускную способность. Виновник? Неэффективное HTTP-кэширование. Без правильных заголовков кэширования браузеры повторно скачивают одни и те же ресурсы при каждом посещении, а CDN не могут эффективно выполнять свою работу.
HTTP-кэширование — одна из самых эффективных оптимизаций производительности. Оно снижает задержки, сокращает затраты на пропускную способность и облегчает нагрузку на исходные серверы. В этом руководстве мы разберём ключевые механизмы: ETag, Cache-Control и то, как в эту картину вписываются CDN. Вы узнаете практические стратегии для их правильной реализации.
Как работает HTTP-кэширование: общая картина
Когда браузер запрашивает ресурс, он может либо получить его с исходного сервера, либо использовать локально сохранённую копию. HTTP-кэширование определяет правила, когда сохранённая копия считается свежей, а когда её нужно перепроверить.
Существует два основных типа кэширования:
- Кэширование в браузере (приватное): Браузер пользователя сохраняет ресурсы локально. Это приносит пользу одному пользователю на нескольких страницах или при повторных посещениях.
- Общее кэширование (CDN, прокси): Промежуточные серверы кэшируют ресурсы для множества пользователей. Это снижает нагрузку на ваш исходный сервер и ускоряет доставку по всему миру.
Оба типа полагаются на HTTP-заголовки для определения свежести и перепроверки. Два наиболее важных заголовка — Cache-Control и ETag.
Cache-Control: правила свежести
Cache-Control — основной заголовок для определения политик кэширования. Это заголовок на основе директив, который сообщает кэшам, как обрабатывать ответ.
Ключевые директивы
- max-age: количество секунд, в течение которых ответ считается свежим. Например,
Cache-Control: max-age=3600означает, что ответ свеж в течение 1 часа. - s-maxage: как max-age, но специально для общих кэшей (CDN). Переопределяет max-age для общих кэшей.
- public: ответ может кэшироваться любым кэшем, включая общие.
- private: ответ предназначен для одного пользователя и не должен сохраняться общими кэшами.
- no-cache: ответ можно сохранять, но перед каждым использованием необходимо перепроверить его с исходным сервером.
- no-store: ответ не должен сохраняться ни в каком кэше. Используйте для конфиденциальных данных.
- must-revalidate: после устаревания кэш не должен использовать ответ без перепроверки.
- immutable: ответ не изменится в течение срока свежести. Полезно для версионированных ресурсов.
Пример: Cache-Control: public, max-age=31536000, immutable идеален для статических ресурсов с хешированными именами файлов.
ETag и условные запросы
ETag (Entity Tag) — это идентификатор конкретной версии ресурса. Когда ресурс изменяется, ETag меняется. Браузеры используют ETag для условных запросов: они отправляют сохранённый ETag в заголовке If-None-Match. Если ресурс не изменился, сервер отвечает 304 Not Modified без тела, экономя пропускную способность.
Аналогично, Last-Modified работает с If-Modified-Since, но ETag точнее (они могут обнаруживать изменения в пределах одной секунды).
Как генерировать ETag
Большинство веб-серверов и фреймворков генерируют ETag автоматически. Например, в Express.js вы можете включить это с помощью app.set('etag', 'strong'). В Nginx ETag включены по умолчанию для статических файлов.
Сильные ETag (например, "abc123") гарантируют побайтовую идентичность. Слабые ETag (например, W/"abc123") указывают на семантическую эквивалентность, а не на точные байты.
Кэширование CDN: общий кэш в масштабе
CDN (сети доставки контента) действуют как общие кэши, распределённые по всему миру. Они кэшируют ваш контент в пограничных точках, доставляя его пользователям из ближайшей точки присутствия. Это снижает задержки и разгружает ваш исходный сервер.
CDN соблюдают заголовки Cache-Control, но часто имеют собственную конфигурацию. Ключевые концепции:
- Пограничный кэш: локальный кэш CDN. Он хранит ответы на основе ключей кэша (обычно URL + заголовки, такие как
Accept-Encoding). - Origin shield: дополнительный слой кэширования, который сокращает количество запросов к вашему исходному серверу.
- Инвалидация кэша: CDN предоставляют API для очистки кэшированного контента при обновлении ресурсов.
При использовании CDN устанавливайте Cache-Control с s-maxage, чтобы управлять свежестью общего кэша отдельно от кэша браузера. Например: Cache-Control: public, max-age=600, s-maxage=3600 означает, что браузеры кэшируют на 10 минут, а CDN — на 1 час.
Сравнение заголовков кэширования
| Заголовок | Назначение | Пример |
|---|---|---|
Cache-Control |
Определяет правила свежести и кэширования | public, max-age=3600 |
ETag |
Уникальный идентификатор версии ресурса | "abc123" |
Last-Modified |
Временная метка последнего изменения | Wed, 21 Oct 2025 07:28:00 GMT |
Expires |
Устаревшая абсолютная дата истечения срока действия | Wed, 21 Oct 2025 07:28:00 GMT |
Vary |
Указывает заголовки, влияющие на кэширование | Accept-Encoding |
Примечание: Expires вытеснен Cache-Control, но всё ещё используется старыми клиентами.
Практическая стратегия кэширования для веб-приложений
Следуйте этим шагам для реализации эффективного кэширования:
- Добавьте отпечатки к статическим ресурсам: Используйте хешированные имена файлов (например,
app.a1b2c3.js) и устанавливайте длительныйmax-ageсimmutable. Когда файл меняется, хеш меняется, сбрасывая кэш. - Установите подходящий Cache-Control для HTML: HTML обычно должен быть
no-cacheили иметь короткийmax-age, чтобы пользователи быстро получали обновления. ИспользуйтеETagдля перепроверки. - Используйте
Vary: Accept-Encoding: Если вы отдаёте сжатые и несжатые версии, это гарантирует, что кэши будут хранить их отдельно. - Задействуйте CDN с s-maxage: Устанавливайте более длительный
s-maxageдля общих кэшей, чтобы снизить нагрузку на исходный сервер, сохраняя кэш браузера короче при необходимости. - Инвалидируйте с умом: Используйте API очистки CDN при развёртывании критических обновлений. Для статических ресурсов отпечатки позволяют избежать необходимости очистки.
- Следите за коэффициентом попаданий в кэш: Используйте аналитику CDN, чтобы убедиться в эффективности кэша. Низкий коэффициент попаданий означает неправильно настроенные заголовки.
Распространённые ошибки и как их избежать
- Чрезмерное кэширование HTML: Пользователи видят устаревший контент. Используйте
no-cacheили короткийmax-age. - Недостаточное кэширование статических ресурсов: Устанавливайте длительный
max-age(например, 1 год) с отпечатками. - Игнорирование
Vary: Кэши могут отдавать неправильный контент (например, gzip вместо обычного). Всегда устанавливайтеVary: Accept-Encoding. - Забыли
privateдля пользовательских данных: Общие кэши могут раскрыть данные. ИспользуйтеCache-Control: privateдля аутентифицированных ответов. - Неправильное использование
no-store: Это предотвращает любое кэширование, что может навредить производительности. Используйте только для конфиденциальных данных.
Тестирование вашей настройки кэширования
Используйте DevTools браузера (вкладка Network), чтобы проверить заголовки ответов и увидеть, отдаются ли ресурсы из кэша (ищите "(from disk cache)" или "(from memory cache)"). Для поведения CDN используйте curl -I, чтобы проверить заголовки, такие как X-Cache или CF-Cache-Status. Инструменты вроде WebPageTest могут визуализировать кэширование между посещениями.
FAQ
В чём разница между ETag и Last-Modified?
ETag — это непрозрачный идентификатор, который меняется при изменении ресурса, а Last-Modified — это временная метка. ETag точнее, потому что может обнаруживать изменения в пределах одной секунды и не зависит от синхронизации часов.
Когда использовать no-cache вместо no-store?
Используйте no-cache, когда вы хотите, чтобы кэш сохранял ответ, но перепроверял его с исходным сервером перед каждым использованием. Используйте no-store для конфиденциальных данных, которые никогда не должны записываться на диск или в память любым кэшем.
Как CDN обрабатывают инвалидацию кэша?
CDN предоставляют API очистки, которые позволяют удалять определённые URL или целые каталоги из их пограничных кэшей. Некоторые также поддерживают мягкую очистку, которая помечает контент как устаревший и перепроверяет его при следующем запросе. Добавление отпечатков к ресурсам часто эффективнее, чем очистка.
Заключение
Освоение HTTP-кэширования с помощью ETag, Cache-Control и CDN необходимо для создания быстрых и масштабируемых веб-приложений. Начните с установки правильных заголовков для ваших статических ресурсов и HTML, используйте общие кэши CDN с s-maxage и всегда тестируйте свою конфигурацию. Небольшие изменения в заголовках кэширования могут привести к значительному повышению производительности.
Нужно быстро проанализировать логи сервера, чтобы увидеть коэффициент попаданий в кэш? Попробуйте наш Nginx Log Analyzer для парсинга и визуализации логов доступа.