Ograniczniki szybkości projektowania
1) Dlaczego ograniczenie stawki
Ograniczenie stawek chroni dostępność i ekonomię API: zatrzymuje powodzie, wybucha przekaźniki, poświadczalne nadziewanie, chroni kosztowne operacje (transakcje pieniężne, generowanie raportów), wygładza obciążenie systemów zależnych (bazy danych/dostawcy danych). Dobra konstrukcja zapewnia uczciwość, przewidywalność opóźnień i jasne SLO.
Kluczowe cele
Stabilność RPS i zabezpieczenie przed przeciążeniem pleców.
Kontrolowana „elastyczność” (dodatek pęknięcia).
Zróżnicowanie klienta (na użytkownika/na organizację/na klucz/na IP/na region).
Model wartości: różne „ceny” dla różnych transakcji.
2) Typy limitów
Limity RPS: żądania na sekundę/minutę.
Kwoty: całkowity budżet na okres (dzień/miesiąc).
Konkurencyjność: operacje jednoczesne (realizacja transakcji, ciężka praca).
Oceń/Stripe Bytes/sec (Ładuj/Rozładuj).
Limity ważone: „koszt” żądania ze względu na złożoność (na przykład złożoność GraphQL, wielkość partii).
Adaptacyjne: zaostrzone w przypadku nieprawidłowości (podejrzana aktywność/błędy 401/403/5xx).
3) Algorytmy i kiedy je stosować
3. 1 Stały licznik okien
Prosty: licznik na przedział (np. 100 r/min).
Plusy: Minimalny koszt. Minusy: „wybucha krawędź” na granicach okna.
Kiedy: panele administratora, niska dokładność, niski koszt.
3. 2 Okno przesuwne (dziennik/licznik)
Log - przechowuje znaczniki czasowe ostatnich zapytań, dokładne, drogie w pamięci.
Licznik: średnia z dwóch sąsiednich okien (walcowanie), kompromis dokładności i ceny.
Kiedy: publiczne interfejsy API średniego ruchu, potrzebujesz gładkości bez skomplikowanej matematyki.
3. 3 wiadro żetonowe
Parametry: szybkość 'r' (żetony/s) i pojemność 'b' (wybuch). Każda prośba „spala” token.
Plusy: naturalny dodatek pęknięcia, proste wdrożenie. Nie ma ścisłej równości.
Kiedy: prawie zawsze dla RPS, jeśli „volleys” są potrzebne w 'b'.
3. 4 Wyciekłe wiadro (kroplówka)
Kolejka, z której „wycieka” ze stałą prędkością.
Plusy: nawet przepływ wyjściowy. Minusy: Więcej opóźnień.
Kiedy: wygładzanie zewnętrznych „delikatnych” dostawców.
3. 5 GCRA (uogólniony algorytm szybkości komórek)
Teoretyczny czas przyjazdu (TAT) model:- 'TAT _ next = max (TAT_current, now) + 1/r', żądanie jest akceptowane, jeśli 'now <= TAT_current + burst/r'.
- Plusy: ścisła, dokładna, mała pamięć (trzymaj TAT kluczem). Wady: trudniejsze do zrozumienia.
Kiedy: potrzebują ścisłej kontroli i gładkości, rozłożone limity.
3. 6 Semafory konkurencyjne
Aktywny licznik operacji; wejście - jeśli istnieją „bilety”; wyjście - zwolnienie.
Kiedy: długotrwałe operacje, wątki, WebSocket, pliki do pobrania.
4) Model klucza limitu
Klucz = kombinacja atrybutów:- 'client _ id'/' api _ key '/' user _ id'/' org _ id'
- „IP/ASN/geo” (ochrona szorstka)
- „punkt końcowy/metoda” (gorące trasy)
- „skop/plan/poziom” (monetyzacja)
- „idempotence _ key” (operacje zapisu)
- Użyj hierarchii: najpierw ścisły per-key, potem per-organization, a następnie globalny.
5) Model kosztów
Zdefiniować „koszt” „koszt (q)”:- GraphQL: złożoność pola × głębokość.
- REST: rozmiar odpowiedzi/żądania, typ operacji (czytaj = 1, zapisz = 3, raport = 10).
- Partia: „koszt = min (n, cap)”.
- Ograniczamy żetony, a nie „żądania”: 'budżet - = koszt (q)'.
6) Realizacja rozproszona
6. 1 Skarbce
Proces: ultra-szybki, ale nie ogólny limit (odpowiedni dla lokalnych „miękkich” limitów).
Redis: de facto standard. INCR/EXPIRE, skrypty Lua (atomicity), ZSET do okna przesuwnego, klawisze z TTL.
Wysłannik/NGINX/Kong/Traefik: wbudowane filtry; wygodne dla obwodu.
Siatka serwisowa: lokalne limity synchronizacji bocznej + globalnej.
6. 2 Atomowość i wyścigi
Lua w Redis: sprawdzanie i przyrost w jednym kroku.
GCRA: przechowywać jeden TAT z CAS/skrypt.
Konsystencja zegara: NTP, zegary monotonowe.
Shading: spójne hash według klucza; unikać „gorących” odłamków.
6. 3 Rozkład geograficzny
Lokalne limity klastrów regionalnych + górna granica globalna (gruba).
CRDT/replikacja - ostrożny (opóźnienia, podwójne zużycie). Preferowane są regionalne limity z marginesem.
7) Polityka i ustalanie priorytetów
Plany: Free/Pro/Enterprise z różnymi kwotami „r”, „b”.
Priorytety: „Drogie” trasy otrzymują mniej limitu lub więcej kosztów.
Listy: allow-list for integrations, denied by ASN/proxy/TOP.
Eskalacja: jeśli przekroczysz ją ponownie, obniżysz limit, wprowadź proof-of-work/captcha/challenges.
8) Przykłady konfiguracji
8. 1 Wysłannik (filtr limitu stawki HTTP, pseudo)
yaml rate_limit:
domain: public-api descriptors:
- key: api_key rate_limit:
unit: second requests_per_unit: 50 burst: 100
- key: api_key value: payments. write rate_limit:
unit: second requests_per_unit: 5 burst: 10
8. 2 NGINX (lua + Redis, pseudo)
nginx lua_shared_dict limits 10m;
location /api/ {
access_by_lua_block {
local key = ngx. var. arg_apikey.. ":".. ngx. var. request_method.. ":".. ngx. var. uri
-- token bucket in Redis (evalsha)
local allowed, retry_after = ratelimit_allow(key, 50, 100) -- r=50/s, b=100 if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}
proxy_pass http://backend;
}
8. 3 Limity konkurencji (kod pseudo)
pseudo on_request_start(key):
if redis. incr_with_ttl("sem:" + key, ttl=60) > MAX_CONCURRENCY:
redis. decr("sem:" + key); reject(429)
on_request_finish(key):
redis. decr("sem:" + key)
8. 4 GCRA (pseudokoda)
pseudo params: r tokens/sec, burst b tat = redis. get(key) or now allowed_time = tat - (b / r)
if now < allowed_time: reject(429, retry_after = allowed_time - now)
tat_next = max(tat, now) + 1/r redis. set(key, tat_next, ttl = ceil(b/r) + safety)
9) Integracja z przekładkami, terminami i wyłącznikiem
Retry-budget: ograniczenie udziału przekaźników do X% głównego ruchu.
Jitter: gdy backoff, zawsze dodać jitter - zmniejsza wybuchy synchroniczne.
Wyłącznik: jeśli występuje wysoki błąd ('5xx', timeouts), obniżyć granice lub przenieść niektóre trasy do „read-only”.
Zabezpieczenie: schludne; rozważyć koszty, aby uniknąć podwojenia budżetu.
10) Obserwowalność i zarządzanie
Метрика: 'rps _ allowed', 'rps _ blocked', '429 _ rate', 'retry _ after _ avg', 'burst _ used', 'quota _ remaining', 'active _ concurrency'.
Etykiety: przez klucz graniczny, region, punkt końcowy, plan.
Dzienniki decyzji (pobrane próbki): przyczyna awarii, bieżące liczniki, klucz TTL.
Deski rozdzielcze: karty ciepła przez klucze/punkty końcowe, „gorące” klientów.
Wpisy: wzrost o 429> 2-5% na trasach krytycznych, częste „wyczerpywanie” kwot, nierównowaga odłamków.
11) Badanie i walidacja
Testy kontraktowe polis (tabele if-then).
Załadunek: pęknięcia (x10 od r), długie płaskowyże, „brudne” wzory (powolne-POST, długie połączenia).
Ruch chaosu: nierówne strumienie, dryf zegara, kropla Redis/siatki.
A/B-włączenie: limity kanaryjskiego rollout, cień-rozwiązania (log, ale nie blokować) przed włączeniem.
12) Przypadki krawędzi i subtelności
Skew zegara: Użyj 'now ()' z jednego źródła (serwera), a nie z nagłówków klienta.
Idempotency-Key: for write - redukuje wzmacnianie w retras.
Operacje serii: ograniczyć wielkość partii i całkowity koszt.
Long-poll/WebSocket: ograniczyć liczbę kanałów/subskrypcji i czas trwania.
Zimny start: „ciepły” start liczników/preload; w przeciwnym razie wybucha fałszywy 429.
Obliczeniowo drogie żądania: ograniczenie do realizacji logiki biznesowej.
Granice TTL: TTL kluczy obejmują okno + margines bezpieczeństwa.
13) Eskalacja przeciwciał
Etapy: ostrzeżenie → 429 + 'Retry-After' → challenge (captcha/puzzle) → tymczasowy blok.
Sygnały: odcisk palca urządzenia, zachowanie kursora/czasu, TOR/proxy/hosting.
Polityka musi być deterministyczna i powtarzalna dla medycyny sądowej.
14) Bezpieczeństwo i zgodność
Odmowa niewykonania zobowiązania na trasach krytycznych (zapis/finansowanie).
Audyt: utrzymywanie decyzji dotyczących ograniczeń w sprawach regulacyjnych i przeglądów incydentów.
PII: klucze limitu nie mogą ujawniać danych osobowych w dziennikach.
15) Lista kontrolna gotowości Prod
- Zdefiniowano klucze graniczne i model kosztów.
- Wybrany algorytm (wiadro tokenowe/GCRA) i przechowywanie (Redis/gateway).
- Zasady dla klientów poziomu + globalne bezpieczniki.
- Limity konkurencji dla transakcji długoterminowych.
- Retry-budget, backoff with jitter, integracja z wyłącznikiem.
- Deski rozdzielcze/wpisy, wyrywkowe dzienniki decyzji.
- Tryb kanaryjski i cień.
- Testy wybuchów, długi płaskowyż, awarie Redis, skew zegara.
- Dokumentacja klienta: 429, kody „Retry-After”, wykładnicze przykłady backoff.
16) TL; DR
Użyj wiadra token lub GCRA z Redis/gateway, klucze limitu projektu i koszty żądania, dodać konkurencyjne semafory dla długich operacji, zintegrować z powtórnym budżetem i wyłącznikiem, monitorować 429 i „przepustowość pęknięcia”, rozwinąć limity poprzez kanaryjski/cień i upewnić się, aby przetestować wybuchy i awarię pamięci