Кэширование HTTP: ETag, Cache-Control, output caching

↑ 5.1 Проектирование REST API · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Про производительность: как снять нагрузку с сервера и не отдавать устаревшие данные.

Объяснение

ЗаголовокСмысл
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 надолго.

Практика

  1. Добавьте ETag и проверьте 304 в DevTools.
  2. Включите Output cache с тегами и инвалидацией.
  3. Реализуйте защиту от stampede через HybridCache.

Вопросы с ответами

Связанные темы