Powrót do strony głównej

Podstawowe RateLimiter .NET: algorytmy i kolejki

Artykuł analizuje podstawowe algorytmiczne ograniczniki uniwersalnego RateLimiter w .NET: FixedWindow, SlidingWindow, TokenBucket i ConcurrencyLimiter. Opisano przetwarzanie żądań, kolejki FIFO/LIFO, Lease i statystyki. Materiał dla senior-programistów.

Architektura podstawowych ograniczników RateLimiter w .NET
Advertisement 728x90

# Podstawowe ograniczniki szybkości w uniwersalnym RateLimiter .NET: architektura i algorytmy

Uniwersalny komponent ograniczania szybkości .NET zawiera cztery podstawowe algorytmiczne ograniczniki: FixedWindowRateLimiter, SlidingWindowRateLimiter, TokenBucketRateLimiter i ConcurrencyLimiter. Pierwszy implementuje stałe okno, drugi — przesuwne, trzeci — kubeł tokenów, czwarty ogranicza paralelizm.

Klasy ograniczników szybkości dziedziczą po ReplenishingRateLimiter, który definiuje logikę uzupełniania pozwoleń za pomocą timera. ConcurrencyLimiter dziedziczy bezpośrednio po RateLimiter. Konstruktory przyjmują parametry konfiguracji, zapisywane w kopii Options.

Wszystkie implementują AttemptAcquireCore (synchronizowany), AcquireAsyncCore (asynchroniczny), Dispose/DisposeAsync. Ograniczniki szybkości dodają ReplenishInternal.

Google AdInline article slot

Obsługa żądań pozwoleń

Żądania dzielą się na próbne (permitCount = 0) i rzeczywiste (permitCount > 0). Ujemna wartość powoduje ArgumentOutOfRangeException.

Algorytm obsługi:

  • Sprawdzenie permitCount ≤ AutoReplenishment.MaxPermits.
  • Dla próbnych: jeśli availablePermits > 0 — natychmiastowy sukces.
  • Blokada na Lock (kolejka deque).
  • Jeśli availablePermits ≥ permitCount — wydanie, dekrementacja, odblokowanie.
  • W przeciwnym razie: synchronizowany odmowa lub umieszczenie w kolejce (asynchronicznie).

Metoda asynchroniczna zwraca ValueTask<RateLimitLease>. Przy przepełnieniu kolejki — odmowa.

Google AdInline article slot

Struktura kolejki żądań

Kolejka to deque<RequestRegistration>, gdzie RequestRegistration dziedziczy po TaskCompletionSource<RateLimitLease>.

Ustawienia kolejki w Options:

  • QueueLimit: maksymalna suma permitCount w kolejce.
  • QueueProcessingOrder: OldestFirst (FIFO, domyślnie) lub NewestFirst (LIFO).

Bieżący rozmiar: _queueTotalPermits. Blokada na deque.

Google AdInline article slot

Przy uzupełnianiu pozwoleń: Dequeue, CompleteTask z udanym Lease, dekrementacja _queueTotalPermits.

Zwrot Lease i statystyki

Metody zwracają klasy pochodne od RateLimitLease:

  • FixedWindowLease, SlidingWindowLease, TokenBucketLease (podobne).
  • ConcurrencyLease (różni się).

Liczniki: _successfulAcquires, _failedAcquires (Interlocked.Increment).

RateLimiterStatistics kopiuje:

  • AvailablePermits.
  • CurrentQueueLength.
  • Liczniki.

Właściwość IdleDuration: czas bezczynności bez żądań.

Cechy każdego ogranicznika

FixedWindowRateLimiter

Stałe okno: pozwolenia uzupełniane na początku okna (permitPeriod).

_availablePermits resetowane na MaxPermits.

SlidingWindowRateLimiter

Przesuwne okno: śledzi historię w SlidingWindowSize segmentach (segmentSize = permitPeriod / SlidingWindowSize).

Odtwarza na podstawie poprzednich segmentów.

TokenBucketRateLimiter

Kubeł tokenów: _tokens uzupełniane co ReplenishmentPeriod, rate = TokensPerPeriod.

Ogranicza zużycie według refillAmount.

ConcurrencyLimiter

Ogranicza _currentConcurrency ≤ PermitLimit.

Kolejka uruchamia zadania po zakończeniu aktywnych (OnCompleted).

Co ważne

  • Uniwersalność: podstawowe ograniczniki — podstawa rate limitingu w ASP.NET Core, stosowalne poza kontekstem webowym.
  • Kolejka: obsługa FIFO/LIFO, limit według sumy permits, asynchroniczne wykonanie.
  • Próby żądań: permitCount=0 do sprawdzenia bez zużycia.
  • Statystyki: atomowe liczniki + metryki w czasie rzeczywistym.
  • Uzupełnianie: napędzane timerem dla wszystkich ReplenishingRateLimiter.

— Editorial Team

Advertisement 728x90

Czytaj dalej