Rate Limiting в C# (.NET): Полное руководство по библиотеке System.Threading.RateLimiting

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Rate Limiting в C# (.NET): Библиотека System.Threading.RateLimiting

Rate limiting (ограничение скорости запросов) — критически важный механизм для защиты API, микросервисов и веб-приложений от перегрузок, DDoS-атак и неконтролируемого потребления ресурсов. В экосистеме .NET начиная с .NET 7 появилась встроенная библиотека System.Threading.RateLimiting, которая предоставляет гибкие и производительные инструменты для реализации различных стратегий ограничения.

Что такое Rate Limiting и зачем он нужен?

Rate limiting позволяет контролировать количество операций (запросов, вызовов методов, транзакций) за определенный промежуток времени. Основные сценарии использования:

  • Защита публичных API — предотвращение злоупотреблений со стороны клиентов.
  • Стабилизация бэкенда — равномерное распределение нагрузки на базы данных и внешние сервисы.
  • Экономия ресурсов — ограничение вызовов платных сторонних API.
  • Обеспечение SLA — гарантия равного доступа для всех пользователей.

Основные компоненты библиотеки System.Threading.RateLimiting

Библиотека построена вокруг абстрактного класса RateLimiter и нескольких готовых реализаций:

1. TokenBucketRateLimiter (Алгоритм "Ведро токенов")

Классический алгоритм, который накапливает токены с заданной скоростью (replenishment rate) и позволяет использовать их по мере необходимости. Подходит для сглаживания пиковых нагрузок.

using System.Threading.RateLimiting;

var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions
{
    TokenLimit = 100,           // Максимальное количество токенов
    TokensPerPeriod = 20,       // Сколько токенов добавляется за период
    ReplenishmentPeriod = TimeSpan.FromSeconds(1), // Период пополнения
    QueueLimit = 10,            // Максимальный размер очереди ожидания
    QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});

// Пример использования
using var lease = await limiter.AcquireAsync(cancellationToken: CancellationToken.None);
if (lease.IsAcquired)
{
    // Выполнить операцию
    Console.WriteLine("Токен получен");
}
else
{
    // Обработать отказ
    Console.WriteLine("Превышен лимит, попробуйте позже");
}

2. ConcurrencyLimiter (Ограничение параллелизма)

Ограничивает количество одновременных операций. Идеально для контроля доступа к ограниченным ресурсам (пулы соединений, файловые дескрипторы).

var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
{
    PermitLimit = 10,           // Максимум 10 одновременных запросов
    QueueLimit = 5,             // Очередь ожидания до 5 запросов
    QueueProcessingOrder = QueueProcessingOrder.NewestFirst
});

// Использование в асинхронном контексте
async Task ProcessRequestAsync()
{
    using var lease = await concurrencyLimiter.AcquireAsync();
    if (lease.IsAcquired)
    {
        // Выполняем ресурсоемкую задачу
        await Task.Delay(1000);
    }
}

3. FixedWindowRateLimiter (Фиксированное окно)

Самый простой алгоритм: разрешает N операций за фиксированный интервал времени (например, 100 запросов в минуту). После окончания окна счетчик сбрасывается.

var fixedWindow = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions
{
    PermitLimit = 60,               // 60 запросов
    Window = TimeSpan.FromMinutes(1), // за 1 минуту
    QueueLimit = 0,                 // Без очереди
    AutoReplenishment = true        // Автоматический сброс окна
});

// Проверка лимита
RateLimitLease lease = fixedWindow.AttemptAcquire();
if (lease.IsAcquired)
{
    Console.WriteLine($"Осталось попыток: {lease.GetAllMetadata()}");
}

4. SlidingWindowRateLimiter (Скользящее окно)

Более точный аналог FixedWindow: учитывает запросы в скользящем временном интервале, разбитом на сегменты. Предотвращает "рывки" на границах окон.

var slidingWindow = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
{
    PermitLimit = 100,
    Window = TimeSpan.FromSeconds(30),
    SegmentsPerWindow = 6,          // Каждый сегмент = 5 секунд
    QueueLimit = 0
});

Интеграция с ASP.NET Core

Для веб-приложений библиотека предоставляет middleware, который легко подключается через builder.Services.AddRateLimiter():

// Program.cs (.NET 8+)
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRateLimiter(options =>
{
    options                    

Рекомендаций