Кэширование HTTP: ETag, Cache-Control, output caching
↑ 5.1 Проектирование REST API · ← Предыдущая · → Следующая
Зачем это на собесе
Про производительность: как снять нагрузку с сервера и не отдавать устаревшие данные.
Объяснение
| Заголовок | Смысл |
|---|---|
Cache-Control: max-age=60 | можно использовать без запроса 60 секунд |
Cache-Control: no-store | не кэшировать (чувствительные данные) |
Cache-Control: private/public | кэшировать только в браузере / и в общих кэшах |
ETag: "abc" + If-None-Match | условный запрос: если не изменилось — 304 Not Modified без тела |
Last-Modified + If-Modified-Since | то же по времени |
Vary: Accept-Encoding, Authorization | от каких заголовков зависит ответ |
app.MapGet("/products/{id}", async (int id, HttpContext ctx, IProducts p) =>
{
var product = await p.GetAsync(id);
var etag = $"\"{product.Version}\"";
if (ctx.Request.Headers.IfNoneMatch == etag) return Results.StatusCode(304);
ctx.Response.Headers.ETag = etag;
ctx.Response.Headers.CacheControl = "public,max-age=60";
return Results.Ok(product);
});Серверные кэши ASP.NET Core
- Output caching (
AddOutputCache,.CacheOutput()): кэш ответа на сервере с политиками, тегами и инвалидацией. - Response caching: на основе заголовков, для HTTP-кэшей.
IMemoryCache/IDistributedCache/HybridCache(.NET 9): кэш данных, а не ответов.
builder.Services.AddOutputCache(o => o.AddPolicy("products", b => b.Expire(TimeSpan.FromMinutes(1)).Tag("products")));
app.MapGet("/products", ...).CacheOutput("products");
await cache.EvictByTagAsync("products", ct); // инвалидация при измененииНюансы и подводные камни
- Кэшировать персонализированные ответы в общем кэше нельзя (
privateилиVary: Authorization). - Инвалидация — самая сложная часть: тегируйте и очищайте по событиям.
- Cache stampede: много запросов одновременно при истечении; используйте блокировку/
HybridCache. - Оптимистичная конкуренция через ETag +
If-Matchсовмещает кэш и версионирование. - Не кэшируйте ошибки и 5xx надолго.
Практика
- Добавьте ETag и проверьте 304 в DevTools.
- Включите Output cache с тегами и инвалидацией.
- Реализуйте защиту от stampede через
HybridCache.
Вопросы с ответами
Как работает ETag?
Клиент отправляет
If-None-Matchс прошлым ETag; если ресурс не менялся, сервер отвечает 304 без тела.
Чем output cache отличается от IMemoryCache?
Output cache кэширует готовый HTTP-ответ,
IMemoryCache— произвольные данные.
Что такое cache stampede?
Одновременное обновление истекшего ключа множеством запросов, создающее пик нагрузки.