Redis, nazývaný aj Remote Dictionary Server, je open-source in-memory databáza. Je to dátovo štruktúrovaný úložný systém, ktorý beží v pamäti RAM servera, čo je oveľa rýchlejšie ako najrýchlejší Solid State Drive (SSD). V dôsledku toho je Redis veľmi responzívny a vynikajúco sa hodí na obmedzovanie frekvencie požiadaviek (rate limiting).
Obmedzovanie frekvencie obmedzuje počet opakovaní, koľkokrát môže používateľ požiadať o prostriedok zo servera. Mnohé služby využívajú obmedzenia frekvencie na zabránenie zneužívaniu služieb, napríklad keď sa používateľ pokúsi preťažiť server príliš veľkou záťažou. Napríklad pri použití PHP na vývoj verejného API (Application Programming Interface) pre vašu webovú aplikáciu sú obmedzenia frekvencie nevyhnutné. Je to preto, že keď sprístupníte API verejnosti, budete chcieť obmedziť, koľkokrát môže jednotlivec zopakovať aktivitu za určitý čas. Používatelia, ktorí nemajú nad vaším systémom žiadnu kontrolu, by ho mohli úplne ochromiť.
Obmedzovanie frekvencie umožňuje vašej aplikácii fungovať hladko tým, že odmieta požiadavky používateľov, ktoré prekračujú stanovený limit. Ak máte veľký počet klientov, obmedzenie frekvencie zavádza pravidlá férového používania (fair-use policy), ktoré umožňujú každému používateľovi pristupovať k vašej aplikácii vysokou rýchlosťou. Obmedzovanie frekvencie vám tiež môže pomôcť ušetriť peniaze za šírku pásma znížením preťaženia vášho servera.
Sledovaním aktivity používateľov v databáze, ako je MySQL, by bolo možné vytvoriť program na obmedzovanie frekvencie. Keďže by sa však takéto údaje museli sťahovať z disku a vyhodnocovať voči definovanému limitu, výsledný efekt by nemusel byť škálovateľný, keď systém kontaktuje viacero ľudí súčasne. Nielenže je to neefektívne, ale systémy riadenia relačných databáz na to neboli stvorené.
Redis je dobrou voľbou na vytvorenie obmedzovača frekvencie, pretože funguje ako in-memory databáza a bol overený ako spoľahlivý na tento účel. V tomto návode vás prevedieme krokmi implementácie obmedzovania frekvencie v PHP pomocou Redis na Ubuntu 20.04.
Poďme na to!
Požiadavky
Na absolvovanie tohto návodu budete potrebovať nasledovné:
-
Najnovšiu verziu systému Ubuntu nainštalovanú vo vašom systéme.
-
Systémoví používatelia musia mať práva sudo.
-
A LAMP stack.
-
Nastavte ho podľa návodu Ako nastaviť LAMP Stack.
-
-
Redis server.
-
Postupujte podľa návodu Ako nainštalovať a zabezpečiť Redis Server na nastavenie Redis vo vašom systéme.
-
Krok 1: Inštalácia rozšírenia Redis pre PHP
Skôr než začneme, aktualizujme repozitáre, aby sme predišli konfliktom balíkov:
|
1 |
sudo apt update |
Ďalej nainštalujte php-redis rozšírenie, balík, ktorý umožňuje používať Redis v programoch PHP. Spustením nasledujúceho príkazu sudo nainštalujte php-redis:
|
1 |
sudo apt install -y php-redis |
Potom reštartujte Apache server, aby sa načítala php-redis knižnica:
|
1 |
sudo systemctl restart apache2 |
Ďalším krokom je aktualizácia informácií v indexe softvéru a inštalácia knižnice Redis pre PHP. Potom vytvoríme PHP skript, ktorý obmedzuje prístup na základe IP adresy používateľa.
Krok 2: Vytvorenie webového prostriedku PHP na obmedzovanie frekvencie
V tomto kroku vytvoríte demo.php súbor v koreňovom adresári vášho webového servera ( /var/www/html/). Tento súbor bude prístupný verejnosti a používatelia budú môcť otvoriť túto URL adresu vo svojom preferovanom webovom prehliadači. Neskôr použijeme príkaz curl na overenie dostupnosti prostriedku, ktorý chceme použiť. Používatelia môžu k ukážkovému súboru pristúpiť trikrát v priebehu 15 sekúnd. Pokus o prekročenie maximálneho limitu vyvolá chybové hlásenie.
Hlavná funkcionalita tohto súboru výrazne závisí od servera Redis. PHP kód v súbore vytvorí kľúč na serveri Redis v závislosti od IP adresy používateľa, keď používateľ pristúpi k prostriedku prvýkrát. Kód sa pokúsi porovnať IP adresu používateľa s kľúčmi uloženými v serveri Redis a ak kľúč existuje, keď sa používateľ vráti k prostriedku, zvýši hodnotu o jedna. PHP kód bude neustále kontrolovať, či nová hodnota nedosiahla maximálnu povolenú hodnotu.
Po 15 sekundách platnosť kľúča Redis, ktorý je založený na IP adrese používateľa, vyprší a sledovanie návštev používateľa na webovom zdroji sa začne znova. Otvorte /var/www/html/demo.php súbor v nano textovom editore:
|
1 |
sudo nano /var/www/html/demo.php |
Potom vyplňte všetky polia na inicializáciu triedy Redis. Nezabudnite nastaviť REDIS_PASSWORD na správnu hodnotu:
|
1 2 3 4 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); |
Redis->auth podporuje autentifikáciu servera Redis v čistom texte. To funguje dobre, ak pracujete lokálne (cez localhost), ale ak pracujete so vzdialeným serverom Redis, autentifikácia SSL sa odporúča.
Ďalej v tom istom súbore nastavte nasledujúce premenné na ich predvolené hodnoty:
|
1 2 3 4 5 |
. . . $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; |
Poďme si tieto príkazy podrobne vysvetliť:
-
$max_calls_limit: Používateľ nemôže pristupovať k zdroju nad tento maximálny limit volaní.
-
$time_period: Používa sa ako časový rámec a počíta sa v sekundách. Tu má používateľ povolený prístup k zdroju podľa limitov nastavených v $max_calls_limit .
-
$total_user_calls: Sčítava počet prípadov, kedy používateľ požiadal o prístup k calls limitu v danom časovom období.
Potom pridajte nasledujúci kód na získanie IP adresy žiadateľa o prístup k webovej stránke:
|
1 2 3 4 5 6 7 8 9 10 |
. . . if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $user_ip_address = $_SERVER['HTTP_CLIENT_IP']; } elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $user_ip_address = $_SERVER['REMOTE_ADDR']; } |
Ako ukážka tento kód zaznamenáva akcie používateľov podľa ich IP adries. Ak máte na serveri chránený zdroj, ktorý vyžaduje autentifikáciu, môžete sledovať akcie používateľov pomocou ich používateľských mien alebo prístupových tokenov.
V našom návode bude každému používateľovi, ktorý sa prihlási do vášho systému, priradený jedinečný identifikátor (napríklad ID zákazníka, ID vývojára, ID predajcu alebo dokonca ID používateľa). Nezabudnite použiť tieto ID namiesto $user_ip adresy ak postupujete podľa nášho návodu.
Tu stačí IP adresa používateľa na demonštráciu tohto konceptu. Po získaní IP adresy používateľa z predchádzajúceho úryvku kódu pridajte do súboru nasledujúci blok kódu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
. . . if (!$redis->exists($user_ip_address)) { $redis->set($user_ip_address, 1); $redis->expire($user_ip_address, $time_period); $total_user_calls = 1; } else { $redis->INCR($user_ip_address); $total_user_calls = $redis->get($user_ip_address); if ($total_user_calls > $max_calls_limit) { echo "Používateľ " . $user_ip_address . " limit prekročený."; exit(); } } echo "Vitajte " . $user_ip_address . " celkový počet volaní " . $total_user_calls . " za " . $time_period . " sekúnd"; |
Tu je prehľad týchto príkazov:
-
if...else: Tento príkaz overuje, či je na serveri Redis definovaný kľúč s IP adresou.
-
Ak sa kľúč nenájde, if (!$redis->exists($user_ip_address)) {...}, môžete nastaviť kľúč a definovať jeho hodnotu na 1 pomocou $redis->set($user_ip_address, 1).
-
-
$redis->expire($user_ip_address, $time_period): Nastavuje vypršanie platnosti kľúča v určenom čase. V tomto návode sme ho nastavili na 15 sekúnd.
-
Ak sa IP adresa používateľa nenájde v kľúči Redis, nastavte premennú $total_user_calls hodnotu ako 1.
-
else {...}: Blok príkazov používa $redis->INCR($user_ip_address); príkaz na zvýšenie hodnoty kľúča Redis o 1. Toto sa použije pre každú IP adresu priradenú ku kľúču.
-
Note: Toto môžete dosiahnuť iba vtedy, keď je kľúč už nastavený na serveri Redis a počíta sa ako opakovaná požiadavka.
-
-
$total_user_calls = $redis->get($user_ip_address): Tento príkaz načíta celkový počet požiadaviek overením ich príslušného kľúča založeného na IP adrese na serveri Redis.
-
if ($total_user_calls > $max_calls_limit) {... }..: Tento if príkaz sa používa na overenie prekročenia limitu. Ak áno, upozorníte používateľa pomocou echo "Používateľ" . $user_ip_address . " prekročil limit.";.
Nakoniec používateľa informujete o počte jeho návštev za určené obdobie pomocou príkazu echo "Vitajte" . $user_ip_address . "celkový počet volaní" . $total_user_calls . "za" . $time_period . "sekúnd"; .
Potom pridajte nasledujúce riadky kódu do vášho súboru /var/www/html/demo.php súboru:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $user_ip_address = $_SERVER['HTTP_CLIENT_IP']; }elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $user_ip_address = $_SERVER['REMOTE_ADDR']; } if (!$redis->exists($user_ip_address)) { $redis->set($user_ip_address, 1); $redis->expire($user_ip_address, $time_period); $total_user_calls = 1; } else { $redis->INCR($user_ip_address); $total_user_calls = $redis->get($user_ip_address); if ($total_user_calls > $max_calls_limit) { echo "Používateľ " . $user_ip_address . " prekročil limit."; exit(); } } echo "Vitajte " . $user_ip_address . " celkový počet volaní " . $total_user_calls . " za " . $time_period . " sekúnd"; ?> |
Po dokončení úprav súbor uložte a zatvorte /var/www/html/demo.php súbor po dokončení jeho úprav. Na demo.php webovej stránke ste teraz vytvorili logiku potrebnú na obmedzenie frekvencie požiadaviek používateľov. V nasledujúcom kroku náš skript otestujeme.
Krok 3: Spustenie testu obmedzenia frekvencie požiadaviek v Redis
V tomto kroku použijete príkaz curl na vyžiadanie webového zdroja, ktorý ste napísali v Kroku 2. Ak chcete skript dôkladne otestovať, zadajte jeden príkaz, ktorý si vyžiada zdroj päťkrát. To sa dá dosiahnuť pridaním zástupného argumentu URL do demo.php konca súboru. Na vykonanie curl inštrukcií päťkrát, použite hodnotu ?[1-5] na konci vašej požiadavky.
Spustite nasledujúci curl príkaz nižšie:
|
1 |
curl -H "Accept: text/plain" -H "Content-Type: text/plain" -X GET http://localhost/demo.php?[1-5] |
Keď spustíte kód, mali by ste dostať niečo takéto:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[1/5]: http://localhost/demo.php?1 --> <stdout> --_curl_--http://localhost/demo.php?1 Vitajte 127.0.0.1 celkovo volaní uskutočnených 1 za 15 sekúnd [2/5]: http://localhost/demo.php?2 --> <stdout> --_curl_--http://localhost/demo.php?2 Vitajte 127.0.0.1 celkovo volaní uskutočnených 2 za 15 sekúnd [3/5]: http://localhost/demo.php?3 --> <stdout> --_curl_--http://localhost/demo.php?3 Vitajte 127.0.0.1 celkovo volaní uskutočnených 3 za 15 sekúnd [4/5]: http://localhost/demo.php?4 --> <stdout> --_curl_--http://localhost/demo.php?4 Používateľ 127.0.0.1 limit prekročený. [5/5]: http://localhost/demo.php?5 --> <stdout> --_curl_--http://localhost/demo.php?5 Používateľ 127.0.0.1 limit prekročený. |
Prvé tri požiadavky, ako môžete vidieť, prebehli bez problémov. Štvrtý a piaty dopyt však boli vaším skriptom obmedzené. Je vysoko pravdepodobné, že server Redis spomaľuje rýchlosť, akou môžu ľudia odosielať dopyty.
Pre dve premenné uvedené nižšie v tejto príručke ste zadali nízke hodnoty:
|
1 2 3 4 |
... $max_calls_limit = 3; $time_period = 15; ... |
Pri nasadzovaní aplikácie do produkčného prostredia by ste mali zvážiť použitie vyšších hodnôt v závislosti od toho, ako často očakávate, že ju ľudia budú používať.
Pred úpravou týchto čísel je dobré preskúmať štatistiky v reálnom čase. Ak napríklad protokoly vášho servera ukazujú, že priemerný používateľ navštívi vašu aplikáciu 1 000-krát každých 60 sekúnd, môžete toto číslo použiť ako príklad toho, akú mieru obmedzenia použiť.
Záver
V tejto príručke ste sa naučili, ako používať server Redis s PHP na Ubuntu 20.04. Hoci tento príspevok ukazuje, ako funguje obmedzovanie rýchlosti s Redisom, môžete si ho prispôsobiť tak, aby vyhovoval potrebám vašej webovej aplikácie. Odporúčame vám preskúmať reálne príklady, ako napríklad maximálny limit požiadaviek Twitteru, Google Custom Search JSON API, a ďalšiu podobnú dokumentáciu, aby ste si rozšírili svoje znalosti o obmedzovaní rýchlosti a vyskúšali si experimentovanie s rôznymi časovými limitmi.
Okrem toho existuje mnoho ďalších vzdelávacích materiálov o Redise a PHP, ku ktorým máte prístup na našich blogoch:
- Nasadenie PHP aplikácie na Kubernetes cluster s Ubuntu 18.04
- Inštalácia a zabezpečenie PHPmyadmin na Ubuntu 20.04
- Ako nainštalovať LEMP Stack (Linux Nginx MySQL PHP) na Ubuntu 20.04
Príjemnú prácu!
Komentáre
Zatiaľ žiadne komentáre. Buďte prvý.