Powrót do strony głównej

Rate limiting ASP.NET Core: konfiguracja i algorytmy

Przewodnik po konfiguracji rate limiting w ASP.NET Core. Opisano algorytmy (Fixed Window, Token Bucket), polityki, kolejki i obsługa odmów. Przykłady kodu do integracji w projekty.

Rate Limiting w ASP.NET Core: algorytmy i polityki
Advertisement 728x90

# Konfiguracja rate limiting w ASP.NET Core: przewodnik krok po kroku dla programistów

Funkcja ograniczania szybkości żądań (rate limiting) w ASP.NET Core pozwala kontrolować obciążenie serwera, chroniąc przed atakami DoS i zapewniając sprawiedliwy podział zasobów. Konfiguracja wymaga dwóch kroków: rejestracji usług i dodania middleware do potoku. Wszystkie zależności są zawarte w SDK bez dodatkowych pakietów.

W Program.cs wywołaj AddRateLimiter na WebApplicationBuilder.Services:

builder.Services.AddRateLimiter(options =>
{
    // Konfiguracja polityk
});

Następnie dodaj middleware:

Google AdInline article slot
app.UseRateLimiter();

To podstawowa integracja. Dalej — szczegóły algorytmów i polityk.

Algorytmy i selektywność ograniczania

ASP.NET Core obsługuje kilka algorytmów rate limiting:

  • Fixed Window — stałe okno czasowe, proste, ale z pikami obciążenia.
  • Sliding Window — przesuwne okno, równomierniej rozkłada limity.
  • Token Bucket — kubeł z tokenami, pozwala na burst-traffic.
  • Concurrency Limiter — ograniczenie liczby równoległych żądań.

Selektywność określa, które żądania ograniczać. Globalny limitator stosowany jest do wszystkich, selektywne — według kluczy (IP, user ID).

Google AdInline article slot

Przykład globalnego limitatora (100 żądań na minutę):

options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(
    httpContext => RateLimitPartition.GetFixedWindowLimiter(
        partitionKey: httpContext.Request.Headers.Host.ToString(),
        factory: partition => new FixedWindowRateLimiterOptions
        {
            AutoReplenishment = true,
            PermitLimit = 100,
            Window = TimeSpan.FromMinutes(1)
        }));
);

Grupowanie i łączenie limitatorów

Grupowanie według klucza to podstawa selektywności. Użyj AddFixedWindowLimiter lub niestandardowych polityk.

Markerowana lista kluczowych scenariuszy grupowania:

Google AdInline article slot
  • Według IP: partitionKey: httpContext.Connection.RemoteIpAddress?.ToString()
  • Według klienta: partitionKey: httpContext.User.Identity?.Name
  • Według API-endpointu: partitionKey: httpContext.Request.Path
  • Połączony klucz: IP + User-Agent

Łączenie selektywnych limitatorów za pomocą AddPolicy:

options.AddPolicy("ip", httpContext =>
{
    var ip = httpContext.Connection.RemoteIpAddress;
    return new FixedWindowRateLimiterOptions
    {
        PermitLimit = 50,
        Window = TimeSpan.FromMinutes(1),
        QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
        QueueLimit = 10
    };
});

Nowa funkcja — łączenie nieselektywnych: kilka globalnych limitatorów z kolejkami.

Kolejki i obsługa odmów

Włącz kolejki, aby wygładzić piki:

  • QueueLimit — maksimum w kolejce.
  • QueueProcessingOrder — kolejność (OldestFirst / NewestFirst).

Działania przy odmowie konfiguruje się globalnie lub per-polityka:

options.OnRejected = (context, token) =>
{
    context.HttpContext.Response.StatusCode = 429;
    context.HttpContext.Response.ContentType = "application/json";
    return context.HttpContext.Response.WriteAsync(
        "{"too many requests. try again later.", token);
};

Nazwane i nienazwane polityki

Nazwane polityki stosuje się atrybutami do kontrolerów/akcji:

[EnableRateLimiting("policy1")]
public class ApiController : ControllerBase { }

Prosta rejestracja:

options.AddPolicy("policy1", httpContext =>
    new TokenBucketRateLimiterOptions
    {
        TokenLimit = 100,
        QueueLimit = 20,
        ReplenishmentPeriod = TimeSpan.FromMinutes(1),
        TokensPerPeriod = 100,
        AutoReplenishment = true
    });

Nienazwane polityki — bonus, nieopisany w dokumentacji MS. Implementowane bezpośrednio przez IRateLimiter w selektorach.

Przykład:

options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext>(
    context => new CustomRateLimiter(context));

public class CustomRateLimiter : FixedWindowRateLimiter
{
    // Niestandardowa logika
}

Powiązanie z trasami: [EnableRateLimiting("api")] lub wyłączenie [DisableRateLimiting].

Co ważne

  • Rate limiting działa na poziomie middleware, przed kontrolerami.
  • Zawsze konfiguruj OnRejected dla 429 Too Many Requests.
  • Używaj kolejek w scenariuszach high-load.
  • Łącz polityki dla granularnej kontroli (IP + endpoint).
  • Nienazwane polityki rozszerzają możliwości poza standardowy API.

— Editorial Team

Advertisement 728x90

Czytaj dalej