HTTP заголовки и управление кешем
Кеширование в API часто контролируется с помощью HTTP-заголовков, которые позволяют серверу и клиенту обмениваться информацией о состоянии и сроке действия данных. Наиболее часто используемые заголовки для управления кешированием включают Cache-Control
, ETag
, и Last-Modified
. Разберем каждый из них подробно.
Использование заголовков Cache-Control, ETag, и Last-Modified
Cache-Control
Заголовок Cache-Control
управляет основными параметрами кеширования, включая время жизни, доступность и применимость кеша. Он может быть настроен как на стороне сервера, так и на стороне клиента. Ключевые директивы включают:
max-age=<seconds>
: определяет максимальное время, в течение которого ресурс считается актуальным. Пример:Cache-Control: max-age=3600
(ресурс актуален в течение часа).no-cache
: требует, чтобы каждый запрос проверялся на сервере перед использованием кешированной копии. Пример:Cache-Control: no-cache
.no-store
: запрещает сохранение копии ресурса ни в кеше клиента, ни в промежуточных кешах. Пример:Cache-Control: no-store
.public
: разрешает кеширование ресурса любыми кешами, включая прокси-серверы. Пример:Cache-Control: public
.private
: ограничивает кеширование ресурса только клиентским кешем, запрещая промежуточным узлам кешировать его. Пример:Cache-Control: private
.must-revalidate
: требует проверки валидности кеша перед его использованием по истечении срока действия. Пример:Cache-Control: must-revalidate
.
ETag
Заголовок ETag
(Entity Tag) используется для уникальной идентификации версии ресурса. Когда ресурс изменяется, его ETag также изменяется, что позволяет эффективно управлять кешированием и проверкой изменений. Примеры:
ETag: "abc123"
: сервер присваивает ресурсу уникальный идентификатор.- При последующих запросах клиент может использовать заголовок
If-None-Match
с сохраненным ETag, чтобы запросить обновление только если ресурс изменился:If-None-Match: "abc123"
. - Если ресурс не изменился, сервер возвращает статус
304 Not Modified
, что позволяет избежать передачи неизменных данных.
Last-Modified
Заголовок Last-Modified
указывает на дату и время последнего изменения ресурса. Он работает в паре с заголовком If-Modified-Since
, который клиент отправляет в запросе, чтобы проверить актуальность кешированных данных. Примеры:
Last-Modified: Tue, 20 May 2023 10:00:00 GMT
: указывает время последнего изменения ресурса.- Клиент отправляет
If-Modified-Since: Tue, 20 May 2023 10:00:00 GMT
в запросе. - Если ресурс не изменился с указанного времени, сервер отвечает статусом
304 Not Modified
.
Настройка предполагаемого (heuristic) кеширования
Предполагаемое кеширование используется, когда сервер не предоставляет явные директивы кеширования. В этом случае клиент или прокси-кеш может применять эвристические методы для определения срока жизни кеша на основе времени последней модификации и времени получения ресурса.
Основные подходы:
- Последнее изменение и получение: вычисление времени жизни кеша как доли от времени, прошедшего с момента последнего изменения ресурса до времени получения ответа.
- Пользовательские алгоритмы: использование специфических для приложения логик, основанных на паттернах доступа и изменении данных.
Пример:
- Время получения ресурса: 12:00.
- Время последнего изменения ресурса: 10:00.
- Время жизни кеша может быть определено как 1 час (половина времени между последним изменением и получением).
Проверка валидности и обновления кеша
Эффективное управление кешем требует механизма проверки валидности кешированных данных и их своевременного обновления. Основные стратегии включают:
-
Заголовки
ETag
иIf-None-Match
: при каждом запросе клиент отправляет сохраненный ETag, сервер сравнивает его с текущей версией и возвращает либо статус304 Not Modified
, либо новую версию ресурса с обновленным ETag. -
Заголовки
Last-Modified
иIf-Modified-Since
: клиент отправляет дату последнего модифицирования, сервер сравнивает ее с текущей датой изменения ресурса и возвращает либо статус304 Not Modified
, либо обновленную версию ресурса. -
Инвалидация кеша: активное управление кешем с использованием инструментов и библиотек для удаления устаревших данных. Например, в Redis можно устанавливать TTL для автоматической инвалидации.
-
Проактивное обновление: предварительное обновление данных в кеше на основе предположений о частоте доступа и изменении данных. Например, использование фоновых задач для периодической проверки и обновления кешированных данных.
Пример кода для реализации проверки валидности с использованием ETag
в Node.js:
const express = require('express');
const app = express();
app.get('/data', (req, res) => {
const data = getDataFromDatabase(); // Функция получения данных
const etag = generateETag(data); // Функция генерации ETag
if (req.headers['if-none-match'] === etag) {
res.status(304).end(); // Возвращаем статус 304, если данные не изменились
} else {
res.setHeader('ETag', etag);
res.json(data); // Возвращаем данные и новый ETag
}
});
function generateETag(data) {
return '"' + require('crypto').createHash('md5').update(JSON.stringify(data)).digest('hex') + '"';
}
app.listen(3000, () => console.log('Server running on port 3000'));
Эти методы и стратегии позволяют эффективно управлять кешированием в API, обеспечивая баланс между производительностью и актуальностью данных.