Кешування в 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 або 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, якщо потрібне серверне кешування для зменшення навантаження та прискорення відгуку на ідентичні запити.