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 Также в библиотеке
Moment.js / Day.js для JavaScript (Node.js): полное руководство с примерами
Отправка SMS на Java: обзор API библиотек (Twilio, Nexmo, SMS-шлюзы)
Очереди задач в C# (.NET): System.Threading.Channels, Hangfire и RabbitMQ