Кеширование в ASP.NET

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

 

Кэширование в памяти (In-Memory Caching)

В проект необходимо подключить библиотеку Microsoft.Extensions.Caching.Memory из Nuget-репозитория

Сначала необходимо зарегистрировать службу в ServiceCollection в Startup.cs

services.AddMemoryCache();

Далее используем объект управления кешем в сервисе или контроллере

public class WeatherService
{
    private readonly IMemoryCache _memoryCache;
    private readonly string _cacheKey = "WeatherData";

    public WeatherService(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public WeatherForecast GetWeather()
    {
        if (!_memoryCache.TryGetValue(_cacheKey, out WeatherForecast forecast))
        {
            // Имитация получения данных
            forecast = FetchWeatherFromApi();

            // Установка кэша с временем жизни
            var cacheOptions = new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
                SlidingExpiration = TimeSpan.FromMinutes(2)
            };

            _memoryCache.Set(_cacheKey, forecast, cacheOptions);
        }

        return forecast;
    }
}

Кэширование распределенного типа (Distributed Caching)

Распределенное кэширование позволяет хранить данные в централизованном хранилище, доступном для нескольких серверов. Если один сервер сохранил элемент кэша, другие серверы также могут его использовать. Существуют популярные реализации для баз данных Redis иди SQL Server, а также специализированные, такие как NCache.

Рассмотрим популярный вариант с использованием БД Redis.

Для данного типа кеширования используется библиотека Microsoft.Extensions.Caching.StackExchangeRedis из Nuget

Регистрируем Redis в Startup.cs

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
    options.InstanceName = "RedisCache";
});

Далее, использование похоже на работу с In-Memory Cache

public async Task<string> GetProductAsync(int productId)
    {
        string cacheKey = $"Product_{productId}";
        string product = await _distributedCache.GetStringAsync(cacheKey);

        if (string.IsNullOrEmpty(product))
        {
            // Имитация получения данных
            product = FetchProductFromDb(productId);

            // Установка кэша
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
            };

            await _distributedCache.SetStringAsync(cacheKey, product, options);
        }

        return product;
    }

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

Кеширование ответов (Response Caching)

Response Caching — это простой и эффективный способ повысить производительность приложений ASP.NET, особенно для повторяющихся запросов с неизменным содержимым. Он используется для кэширования HTTP-ответов с целью улучшения производительности приложения и уменьшения нагрузки на сервер. Этот метод позволяет повторно использовать ранее сгенерированные ответы на идентичные запросы, минимизируя затраты на обработку таких запросов.

Включаем Middleware в Program.cs или Startup.cs

app.UseResponseCaching();

Далее для включения кеширования вывода для конкретного метода контроллера можно использовать атрибуты метода

[HttpGet]
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client, NoStore = false)]
public IActionResult GetWeather()
{
    var weatherData = FetchWeatherFromApi();
    return Ok(weatherData);
}

Данный подход добавляет в HTTP-ответ кэширующие заголовки (Cache-Control, Expires, и др.). Эти заголовки информируют клиентов (браузеры, прокси-серверы) о возможности кэширования ответа на их стороне.

OutputCache (ASP.NET Core 7.0 и выше)

Начиная с версии ASP.NET Core 7.0 во фреймворке появился более современный подход для серверного кэширования.

Он сохраняет сгенерированный ответ на стороне сервера и возвращает его при идентичном запросе, что существенно снижает нагрузку на сервер, так как обработка запроса не повторяется.

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

Настраивается простым добавлением атрибута OutputCache в метод контроллера.

[HttpGet]
[OutputCache(Duration = 60, VaryByQueryKeys = new[] { "category" })]
public IActionResult GetProducts(string category)
{
    var products = FetchProductsByCategory(category);
    return Ok(products);
}

Ключевые различия между ResponseCaсhe и OutputCache

Параметр ResponseCache OutputCache
Место кэширования На стороне клиента и прокси. На стороне сервера.
Цель Управление HTTP-заголовками для кэша. Кэширование сгенерированных ответов.
Гибкость Ограничено заголовками HTTP. Поддерживает фильтрацию по запросам, заголовкам и параметрам.
Производительность Уменьшает количество запросов к серверу. Уменьшает нагрузку на сервер и процесс обработки.
Версия ASP.NET Только ASP.NET Core. ASP.NET Core 7.0 и выше.

 

  • Используйте ResponseCache, если необходимо управлять клиентским и прокси-кэшированием через заголовки HTTP (например, для браузеров).
  • Используйте OutputCache, если нужно серверное кэширование для уменьшения нагрузки и ускорения отклика на идентичные запросы.