Ograniczanie liczby żądań
OxPHP jest dostarczany z wbudowanym mechanizmem ograniczania liczby żądań na IP, więc nie ma żadnych zewnętrznych zależności ani infrastruktury do utrzymania. Po włączeniu śledzi on liczbę żądań dla każdego IP klienta i zwraca odpowiedź 429 Too Many Requests, gdy klient przekroczy skonfigurowany próg.
Jak to działa
Mechanizm ograniczania liczby żądań korzysta z licznika o stałym oknie, kluczowanego adresem IP klienta. Każde IP ma swój własny, niezależny licznik i okno.
- Gdy nadchodzi żądanie, OxPHP wyszukuje IP klienta w swoim wewnętrznym trackerze.
- Jeśli wpis nie istnieje lub bieżące okno wygasło, rozpoczyna się nowe okno z licznikiem ustawionym na zero.
- Licznik zwiększa się przy każdym żądaniu.
- Jeśli licznik przekroczy
RATE_LIMIT, serwer natychmiast zwraca odpowiedź429z nagłówkami o limicie żądań. Żądanie jest odrzucane przed routingiem i wykonaniem kodu PHP.
Żądania odrzucone przez limit nadal pojawiają się w rejestrach dostępu i metrykach.
Konfiguracja
| Zmienna | Domyślnie | Opis |
|---|---|---|
RATE_LIMIT |
0 |
Maksymalna liczba żądań na IP w obrębie okna. 0 całkowicie wyłącza ograniczanie liczby żądań przy zerowym narzucie |
RATE_WINDOW_SECONDS |
60 |
Czas trwania okna ograniczania liczby żądań w sekundach |
# Allow 100 requests per IP per 60-second window
RATE_LIMIT=100
RATE_WINDOW_SECONDS=60Nagłówki odpowiedzi
Odrzucone żądania zwracają odpowiedź 429 Too Many Requests z następującymi nagłówkami:
| Nagłówek | Opis |
|---|---|
Retry-After |
Sekundy do zresetowania bieżącego okna |
x-ratelimit-limit |
Maksymalna liczba żądań dozwolona na okno |
x-ratelimit-remaining |
Żądania pozostałe w bieżącym oknie (0 przy przekroczeniu limitu) |
x-ratelimit-reset |
Sekundy do zresetowania bieżącego okna |
x-request-id |
ID żądania do skorelowania tej odpowiedzi z rejestrami dostępu |
Przykładowa odpowiedź 429:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
x-ratelimit-limit: 100
x-ratelimit-remaining: 0
x-ratelimit-reset: 45
x-request-id: 67e2a1f412341a2b0042
429 Too Many RequestsRozwiązywanie problemów
Legalni użytkownicy są ograniczani limitem żądań
Twój próg może być zbyt niski dla rzeczywistych wzorców ruchu. Sprawdź częstość odpowiedzi 429 w swoich metrykach i odpowiednio dostosuj RATE_LIMIT lub RATE_WINDOW_SECONDS.
Sprawdź liczbę żądań odrzuconych przez limit:
curl http://localhost:9090/metrics | grep rate_limitedRozwiązanie: Zwiększ RATE_LIMIT lub wydłuż RATE_WINDOW_SECONDS, aby dać klientom więcej swobody.
Użytkownicy za firmowym NAT-em współdzielą ten sam licznik IP
OxPHP ogranicza liczbę żądań na podstawie źródłowego IP. Wszyscy użytkownicy za współdzielonym NAT-em lub proxy współdzielą jeden licznik. Jeśli powoduje to problemy, rozważ wyłączenie wbudowanego limitera OxPHP (RATE_LIMIT=0) i zastosowanie ograniczania liczby żądań na wyższym poziomie (np. na load balancerze lub bramce API), gdzie masz dostęp do identyfikatorów użytkowników.
Ustaw TRUSTED_PROXIES, aby ograniczanie liczby żądań korzystało z prawdziwego IP klienta zamiast IP proxy. Zobacz Zaufane proxy.
Ograniczanie liczby żądań nie działa między wieloma instancjami
Limiter OxPHP działa w pamięci i jest per-instancja. Jeśli uruchamiasz wiele instancji OxPHP za load balancerem, każda śledzi własne, niezależne liczniki. Klient może wysłać RATE_LIMIT żądań do każdej instancji bez wywołania odpowiedzi 429. Do skoordynowanego ograniczania liczby żądań między instancjami użyj zewnętrznego limitera na poziomie load balancera lub bramki API.
Zużycie pamięci rośnie podczas ataków z rotacją IP
OxPHP śledzi do 100 000 unikalnych adresów IP. Gdy ten limit zostanie osiągnięty, wygasłe wpisy są usuwane przed dodaniem nowych. Jeśli zaobserwujesz wzrost zużycia pamięci spowodowany przez atakującego szybko zmieniającego IP, automatyczne czyszczenie ogranicza wpływ do ograniczonej ilości pamięci.
Przykład Docker
services:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "8080:80"
environment:
RATE_LIMIT: "100"
RATE_WINDOW_SECONDS: "60"
volumes:
- ./app:/var/www/html:roDobre praktyki
- Zacznij zachowawczo. Rozpocznij od niższego limitu (np. 60 żądań na minutę) i zwiększaj go na podstawie zaobserwowanych wzorców ruchu. Łatwiej jest poluzować limity niż wyjść z przeciążenia serwera.
- Używaj współdzielonego limitera przy wdrożeniach wieloinstancyjnych. Limiter OxPHP działa per-instancja. Do skoordynowanego ograniczania między instancjami zastosuj ograniczanie liczby żądań na poziomie load balancera lub bramki API.
- Monitoruj częstość odpowiedzi 429. Śledź udział żądań odrzuconych przez limit w swoich metrykach, aby wykrywać źle skonfigurowane progi lub nieoczekiwane skoki ruchu.
Uwagi
- Algorytm stałego okna. Limiter korzysta z licznika o stałym oknie, a nie z okna przesuwnego. Klient może wysłać nawet
2xskonfigurowanego limitu w serii na granicy między dwoma oknami. - Tylko na IP. Ograniczanie liczby żądań jest kluczowane źródłowym adresem IP. Nie ma obsługi niestandardowych kluczy, takich jak klucz API czy identyfikator użytkownika.
- Stan w pamięci. Liczniki limitu żądań nie są współdzielone między wieloma instancjami OxPHP.
- Automatyczne czyszczenie. Wygasłe wpisy są usuwane, gdy tracker przekroczy 100 000 IP, usuwając wszystkie wpisy, których okna wygasły.
Zobacz też
- Metryki — monitoruj liczbę żądań odrzuconych przez limit za pomocą Prometheusa
- ID żądań — korelowanie żądań odrzuconych przez limit w rejestrach
- Rejestrowanie dostępu — odpowiedzi 429 pojawiają się w rejestrach dostępu
- Dokumentacja konfiguracji — pełna lista zmiennych środowiskowych