Redis, také nazývaný Remote Dictionary Server, je open-source databáze v operační paměti (in-memory). Jedná se o systém ukládání strukturovaných dat, který běží v paměti RAM serveru, což je mnohem rychlejší než nejrychlejší Solid State Drive (SSD). Díky tomu má Redis velmi rychlou odezvu a skvěle se hodí pro omezování rychlosti.
Omezování rychlosti omezuje počet pokusů, kolikrát může uživatel požádat o prostředek ze serveru. Mnoho služeb využívá limity rychlosti k zamezení zneužívání služeb, například když se uživatel pokusí přetížit server příliš velkou zátěží. Například při použití PHP k vývoji veřejného API (Application Programming Interface) pro vaši webovou aplikaci jsou omezení rychlosti vyžadována. Je to proto, že když zpřístupníte API veřejnosti, budete chtít omezit, kolikrát může jednotlivec opakovat určitou aktivitu v daném časovém úseku. Uživatelé, kteří nemají nad vaším systémem žádnou kontrolu, by jej mohli zcela ochromit.
Omezování rychlosti umožňuje vaší aplikaci hladce fungovat tím, že odmítá požadavky uživatelů, které překračují stanovený limit. Pokud máte velký počet klientů, omezování rychlosti zavádí zásady spravedlivého užívání (fair-use policy), které umožňují každému uživateli přistupovat k vaší aplikaci vysokou rychlostí. Omezování rychlosti vám také může pomoci ušetřit peníze za šířku pásma snížením přetížení vašeho serveru.
Sledováním aktivity uživatelů v databázi, jako je MySQL, by bylo možné vytvořit program pro omezování rychlosti. Jelikož by se však taková data musela stahovat z disku a vyhodnocovat oproti definovanému limitu, výsledné řešení by nemuselo být škálovatelné, pokud by systém kontaktovalo více lidí najednou. Nejenže je to neefektivní, ale systémy pro správu relačních databází pro tento účel nebyly navrženy.
Redis je dobrou volbou pro vytvoření omezovače rychlosti, protože funguje jako databáze v operační paměti a byl pro tento účel ověřen jako spolehlivý. V tomto návodu vás provedeme kroky implementace omezování rychlosti v PHP pomocí Redis na Ubuntu 20.04.
Začněme!
Požadavky
Chcete-li postupovat podle tohoto návodu, budete potřebovat následující:
-
Nejnovější verzi nainstalovaného systému Ubuntu ve vašem systému.
-
Systémoví uživatelé musí mít oprávnění sudo.
-
LAMP stack.
-
Nastavte jej podle návodu Jak nastavit LAMP Stack.
-
-
Redis server.
-
Postupujte podle návodu Jak nainstalovat a zabezpečit Redis Server pro nastavení Redis ve vašem systému.
-
Krok 1: Instalace rozšíření Redis pro PHP
Než začneme, aktualizujme repozitáře, abychom předešli konfliktům balíčků:
|
1 |
sudo apt update |
Dále nainstalujte rozšíření php-redis, což je balíček, který umožňuje používat Redis v programech PHP. Pro instalaci spusťte následující příkaz sudo php-redis:
|
1 |
sudo apt install -y php-redis |
Poté restartujte server Apache, aby se načetla knihovna php-redis :
|
1 |
sudo systemctl restart apache2 |
Dalším krokem je aktualizace informací v indexu softwaru a instalace knihovny Redis pro PHP. Poté vytvoříme PHP skript (prostředek), který omezuje přístup na základě IP adresy uživatele.
Krok 2: Vytvoření webového prostředku PHP pro omezování rychlosti
V tomto kroku vytvoříte soubor demo.php v kořenovém adresáři webového serveru ( /var/www/html/). Tento soubor bude veřejně přístupný a uživatelé budou moci otevřít jeho URL ve svém oblíbeném webovém prohlížeči. Později použijeme příkaz curl k ověření dostupnosti prostředku, který chceme použít. Uživatelé mohou k ukázkovému souboru přistoupit třikrát během 15 sekund. Pokus překračující maximální limit vyvolá chybovou zprávu.
Hlavní funkčnost tohoto souboru silně závisí na serveru Redis. Kód PHP v souboru vytvoří při prvním přístupu uživatele k prostředku klíč na serveru Redis v závislosti na IP adrese uživatele. Při dalším přístupu se kód pokusí porovnat IP adresu uživatele s klíči uloženými na serveru Redis a pokud klíč existuje, zvýší jeho hodnotu o jedna. Kód PHP bude neustále kontrolovat, zda nová hodnota nedosáhla maximálního limitu.
Po 15 sekundách vyprší platnost klíče Redis, který je založen na IP adrese uživatele, a sledování návštěv uživatele na webovém zdroji začne znovu. Otevřete /var/www/html/demo.php soubor v nano textovém editoru:
|
1 |
sudo nano /var/www/html/demo.php |
Poté vyplňte všechna pole pro inicializaci třídy Redis. Nezapomeňte nastavit REDIS_PASSWORD na správnou hodnotu:
|
1 2 3 4 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); |
Redis->auth podporuje ověřování serveru Redis v čistém textu. To funguje dobře, pokud pracujete lokálně (přes localhost), ale pokud pracujete se vzdáleným serverem Redis, SSL ověřování se doporučuje.
Dále ve stejném souboru nastavte následující proměnné na jejich výchozí hodnoty:
|
1 2 3 4 5 |
. . . $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; |
Pojďme si tyto příkazy podrobně vysvětlit:
-
$max_calls_limit: Uživatel nemůže přistupovat ke zdroji nad tento maximální limit volání.
-
$time_period: Používá se jako časový rámec a počítá se v sekundách. Zde je uživateli povolen přístup ke zdroji podle limitů nastavených v $max_calls_limit .
-
$total_user_calls: Sčítá počet pokusů, kdy uživatel požádal o přístup k limitu volání v daném časovém období.
Poté přidejte následující kód pro získání IP adresy žadatele o přístup k webové stránce:
|
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']; } |
Pro demonstraci tento kód zaznamenává akce uživatelů podle jejich IP adres. Pokud máte na serveru chráněný zdroj, který vyžaduje ověření, můžete sledovat akce uživatelů pomocí jejich uživatelských jmen nebo přístupových tokenů.
V našem průvodci bude každému uživateli, který se přihlásí do vašeho systému, přidělen jedinečný identifikátor (například ID zákazníka, ID vývojáře, ID prodejce nebo dokonce ID uživatele). Nezapomeňte použít tato ID namísto $user_ip adresy, pokud postupujete podle našeho návodu.
Zde k předvedení konceptu postačí IP adresa uživatele. Jakmile získáte IP adresu uživatele z předchozího fragmentu kódu, přidejte do souboru následující 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 "Uživatel " . $user_ip_address . " překročil limit."; exit(); } } echo "Vítejte " . $user_ip_address . " celkem provedených volání: " . $total_user_calls . " za " . $time_period . " sekund"; |
Zde je přehled těchto příkazů:
-
if...else: Tento příkaz ověřuje, zda je na serveru Redis definován klíč s IP adresou.
-
Pokud klíč není nalezen, if (!$redis->exists($user_ip_address)) {...}, můžete klíč nastavit a definovat jeho hodnotu na 1 pomocí $redis->set($user_ip_address, 1).
-
-
$redis->expire($user_ip_address, $time_period): Nastaví vypršení platnosti klíče v určený čas. V tomto návodu jsme jej nastavili na 15 sekund.
-
Pokud IP adresa uživatele není v klíči Redis nalezena, nastavte proměnnou $total_user_calls hodnotu jako 1.
-
else {...}: Blok příkazů používá $redis->INCR($user_ip_address); příkaz k navýšení hodnoty klíče Redis o 1. To se použije pro každou IP adresu spojenou s tímto klíčem.
-
Note: Toho lze dosáhnout pouze tehdy, když je klíč již na serveru Redis nastaven a je započítán jako opakovaný požadavek.
-
-
$total_user_calls = $redis->get($user_ip_address): Tento příkaz načte celkový počet požadavků ověřením příslušného klíče založeného na IP adrese na serveru Redis.
-
if ($total_user_calls > $max_calls_limit) {... }..: Tento if příkaz se používá k ověření překročení limitu. Pokud ano, upozorníte uživatele pomocí echo "Uživatel" . $user_ip_address . " překročil limit.";.
Nakonec uživatele informujete o počtu jeho návštěv v určeném období pomocí příkazu echo "Vítejte" . $user_ip_address . "celkový počet volání" . $total_user_calls . "za" . $time_period . "sekund"; příkazu.
Poté přidejte následující řádky kódu do svého souboru /var/www/html/demo.php :
|
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 "Uživatel " . $user_ip_address . " překročil limit."; exit(); } } echo "Vítejte " . $user_ip_address . " celkový počet volání " . $total_user_calls . " za " . $time_period . " sekund"; ?> |
Uložte a zavřete soubor /var/www/html/demo.php poté, co jej upravíte. Na webové stránce demo.php jste nyní vytvořili logiku potřebnou pro omezení rychlosti požadavků uživatelů. Pojďme náš skript otestovat v následujícím kroku.
Krok 3: Spuštění testu omezení rychlosti v Redis
V tomto kroku použijete příkaz curl k vyžádání webového prostředku, který jste napsali v Kroku 2. Chcete-li skript důkladně otestovat, zadejte jediný příkaz, který si prostředek vyžádá pětkrát. Toho lze dosáhnout přidáním zástupného argumentu URL k demo.php konce souboru. Pro provedení curl instrukcí pětkrát, použijte hodnotu ?[1-5] na konci vašeho požadavku.
Spusťte následující curl příkaz níže:
|
1 |
curl -H "Accept: text/plain" -H "Content-Type: text/plain" -X GET http://localhost/demo.php?[1-5] |
Když kód spustíte, měli byste získat něco takového:
|
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 Vítejte 127.0.0.1 celkem volání provedeno 1 za 15 sekund [2/5]: http://localhost/demo.php?2 --> <stdout> --_curl_--http://localhost/demo.php?2 Vítejte 127.0.0.1 celkem volání provedeno 2 za 15 sekund [3/5]: http://localhost/demo.php?3 --> <stdout> --_curl_--http://localhost/demo.php?3 Vítejte 127.0.0.1 celkem volání provedeno 3 za 15 sekund [4/5]: http://localhost/demo.php?4 --> <stdout> --_curl_--http://localhost/demo.php?4 Uživatel 127.0.0.1 limit překročen. [5/5]: http://localhost/demo.php?5 --> <stdout> --_curl_--http://localhost/demo.php?5 Uživatel 127.0.0.1 limit překročen. |
První tři požadavky, jak vidíte, proběhly bez problémů. Čtvrtý a pátý dotaz však byly vaším skriptem omezeny. Je velmi pravděpodobné, že server Redis zpomaluje rychlost, jakou mohou lidé dotazy pokládat.
V této příručce jste pro dvě níže uvedené proměnné zadali nízké hodnoty:
|
1 2 3 4 |
... $max_calls_limit = 3; $time_period = 15; ... |
Při vytváření aplikace v produkčním prostředí byste měli zvážit použití větších čísel v závislosti na tom, jak často předpokládáte, že ji lidé budou používat.
Před úpravou těchto čísel je dobré prozkoumat statistiky v reálném čase. Pokud například protokoly vašeho serveru ukazují, že průměrný uživatel navštíví vaši aplikaci 1 000krát každých 60 sekund, můžete toto číslo použít jako příklad toho, jak velké omezení použít.
Závěr
V této příručce jste se naučili, jak používat server Redis s PHP na Ubuntu 20.04. Přestože tento příspěvek ukazuje, jak funguje omezování rychlosti s Redis, můžete si jej přizpůsobit potřebám své webové aplikace. Doporučujeme vám prozkoumat reálné příklady jako maximální limit požadavků Twitteru, Google Custom Search JSON API, a další podobnou dokumentaci, abyste si rozšířili své znalosti o omezování rychlosti a sami experimentovali s různými časovými limity.
Kromě toho existuje mnoho dalších výukových materiálů o Redis a PHP, ke kterým máte přístup z našich blogů:
- Nasazení PHP aplikace na Kubernetes cluster s Ubuntu 18.04
- Instalace a zabezpečení PHPmyadmin na Ubuntu 20.04
- Jak nainstalovat LEMP Stack (Linux Nginx MySQL PHP) na Ubuntu 20.04
Příjemnou práci!
Komentáře
Zatím žádné komentáře. Buďte první.