Rate limiting
Konfigurace rate limitingu vám umožní omezit počet požadavků, které může uživatel provést za určitý časový úsek. Tímto způsobem můžete ochránit vaši aplikaci před DDoS útoky a zároveň zajistit, že API bude dostupné pro všechny uživatele.
Nastavení rate limitingu
Nejjednodušší možností, jak nastavit rate limiting bez zásahu do samotného kódu aplikace je využítí NGINX Rate Limiteru. Nejprve si ukážeme, jak vypadá stávající konfigurace NGINX, kterou používáme v našem Dockeru. V následujícím odstavci Vysvětlení direktiv a parametrů si pak vysvětlíme jak konfiguraci upravit.
Definice zóny
Téměř na konci bloku http
v souboru docker/nginx/nginx.conf
nelezneme definici zóny pro rate limiting:
http {
# ...
# Definice zóny pro rate limiting
limit_req_zone $http_x_real_ip zone=primaryZone:5m rate=10r/s;
}
Omezení endpointu
Téměř na konci bloku server
v souboru docker/nginx/http.d/default.conf
pak nalezneme konfiguraci pro konkrétní
endpoint, kde chceme rate limiting aplikovat:
server {
# ...
location ~ \.php$ {
# ...
# Aplikace rate limitingu na konkrétní endpoint
# V tomto případě na všechny volání PHP skriptů
limit_req zone=primaryZone burst=5 nodelay;
}
}
Vysvětlení direktiv a parametrů
Direktiva limit_req_zone
Direktiva limit_req_zone
je obvykle definována v bloku http
, takže je dostupná pro použití ve více kontextech.
Vyžaduje následující tři parametry:
key
- Definuje charakteristiku požadavku, proti které je limit aplikován. V příkladu je to NGINX proměnná$http_x_real_ip
, která obsahuje IP adresu klienta. To znamená, že omezujeme každou jedinečnou IP adresu. (Pokud by náš server neběžel v Dockeru za traefik proxy, bylo by mnohem vhodnější použít$binary_remote_addr
, jenž reprezentuje IP adresu klienta v binární podobě a zabírá méně paměti.zone
- Definuje zónu sdílené paměti, která se používá k uložení stavu každé IP adresy a jak často přistupovala ke konkrétnímu endpointu. Uchovávání informací ve sdílené paměti znamená, že informace lze sdílet mezi procesy NGINX workerů. Definice má dvě části: název zóny identifikovaný klíčovým slovemzone=
a velikost za dvojtečkou:
. Informace o stavu pro 16 000 IPs v binární podobě zabere cca 1 MB. V případě použití$http_x_real_ip
je IP reprezentována jako řetězec, takže je potřeba počítat s mnohem větší paměťovou náročností.Pokud je úložiště vyčerpáno a NGINX potřebuje přidat nový záznam, odstraní nejstarší záznam. Pokud uvolněné místo stále nestačí k uložení nového záznamu, NGINX vrátí stavový kód
503 (Service Temporarily Unavailable)
. Navíc, aby se zabránilo vyčerpání paměti, pokaždé, když NGINX vytvoří nový záznam, odstraní až dva záznamy, které nebyly použity v předchozích 60 sekundách.rate
- Nastavuje maximální rychlost požadavků. V příkladu nemůže rychlost překročit 10 požadavků za sekundu. NGINX ve skutečnosti sleduje požadavky s milisekundovou granularitou, takže tento limit odpovídá 1 požadavku každých 100 ms.
Direktiva limit_req_zone
nastavuje parametry pro omezení rychlosti a zónu sdílené paměti. Ve skutečnosti ale neomezuje
rychlost požadavků. K tomu je potřeba použít direktivu limit_req
u konkrétního endpointu.
Direktiva limit_req
Direktiva limit_req
omezuje rychlost požadavků na konkrétním endpointu. Má následující parametry:
zone
- Přiřazuje zónu, která byla definována pomocílimit_req_zone
.burst
- Umožňuje definovat, kolik požadavků nad rámec nastavené rychlosti (rate
) může být dočasně akceptováno předtím, než NGINX začne vracet chybu 503. Tento mechanismus je užitečný pro absorbování nárazových zvýšení počtu požadavků, které jsou typické pro webové aplikace. Například, pokud jerate
nastaven na 10 požadavků za sekundu aburst
na 20, NGINX umožní přijmout 20 požadavků nad rámec normální rychlosti a zařadí je do fronty. Tyto požadavky jsou poté zpracovávány v intervalu určeném parametremrate
. Pokud počet požadavků v queue přesáhne limit nastavený vburst
, začne NGINX vracet chybový kód 503.delay / nodelay
- Slouží k ovlivnění způsobu, jakým NGINX zpracovává požadavky ve frontě.Delay
způsobí, že NGINX bude požadavky ve frontě postupně uvolňovat podle rychlosti nastavené vrate
, což může způsobit zpoždění ve zpracování požadavků. Na druhou stranu,nodelay
umožňuje NGINXu zpracovat všechny požadavky okamžitě, pokud je ve frontě volné místo. Požadavky jsou pak okamžitě předány bez zbytečného čekání, což znamená, že když přijde více požadavků najednou, NGINX je může všechny zpracovat hned, pokud existuje volný slot - pak postupně uvolňuje sloty podle rychlosti nastavené vrate
. Toto nastavení je obzvláště užitečné pro minimalizaci latence a zajištění plynulého toku dat, aniž by se příliš omezovaly rozestupy mezi jednotlivými požadavky.