Redis, također nazvan Remote Dictionary Server, je baza podataka otvorenog koda u radnoj memoriji (in-memory). To je sustav za pohranu strukturiranih podataka koji se izvodi na RAM-u poslužitelja, što je puno brže od najbržeg Solid State Drive-a (SSD). Kao rezultat toga, Redis je vrlo responzivan i izvrstan izbor za ograničavanje brzine.
Ograničavanje brzine ograničava broj puta koliko korisnik može zatražiti resurs s poslužitelja. Mnoge usluge koriste ograničenja brzine kako bi spriječile zlouporabu usluge, kao kada korisnik pokuša preopteretiti poslužitelj prevelikim opterećenjem. Na primjer, kada koristite PHP za razvoj javnog API (Application Programming Interface) za vašu web aplikaciju, potrebna su ograničenja brzine. To je zato što kada izložite API javnosti, željet ćete ograničiti koliko puta pojedinac može ponoviti aktivnost u određenom vremenskom razdoblju. Korisnici koji nemaju ovlasti nad vašim sustavom mogli bi ga dovesti do zastoja.
Ograničavanje brzine omogućuje vašoj aplikaciji nesmetan rad odbijanjem korisničkih zahtjeva koji premašuju postavljeno ograničenje. Ako imate velik broj klijenata, ograničavanje brzine nameće politiku poštene upotrebe koja svakom korisniku omogućuje pristup vašoj aplikaciji velikom brzinom. Ograničavanje brzine također vam može pomoći uštedjeti novac na propusnosti smanjenjem zagušenja na vašem poslužitelju.
Praćenjem korisničkih aktivnosti u bazi podataka poput MySQL, bilo bi moguće stvoriti program za ograničavanje brzine. Međutim, budući da bi se takvi podaci trebali preuzimati s diska i procjenjivati u odnosu na definirano ograničenje, konačni rezultat možda neće biti skalabilan kada više ljudi kontaktira sustav. Ne samo da je to neučinkovito, već rješenja za upravljanje relacijskim bazama podataka nisu stvorena za to.
Redis je dobar izbor za izradu limitatora brzine jer radi kao baza podataka u radnoj memoriji i dokazano je pouzdan za to. U ovom vodiču provest ćemo vas kroz korake implementacije PHP ograničavanja brzine pomoću Redisa na sustavu Ubuntu 20.04.
Počnimo!
Preduvjeti
Kako biste pratili ovaj vodič, trebat će vam sljedeće:
-
Najnovija verzija sustava Ubuntu instalirana na vašem sustavu.
-
Korisnici sustava moraju imati sudo privilegije.
-
A LAMP stack.
-
Postavite ga prateći vodič Kako postaviti LAMP stog .
-
-
Redis poslužitelj.
-
Pratite vodič Kako instalirati i osigurati Redis poslužitelj kako biste postavili Redis na svom sustavu.
-
Korak 1: Instalirajte Redis proširenje za PHP
Prije nego što počnemo, ažurirajmo repozitorije kako bismo izbjegli sukobe paketa:
|
1 |
sudo apt update |
Next, install the php-redis proširenje, paket koji omogućuje korištenje Redisa u PHP programima. Run the following sudo command to install php-redis:
|
1 |
sudo apt install -y php-redis |
After that, restart the Apache server to load the php-redis library:
|
1 |
sudo systemctl restart apache2 |
Sljedeći korak je ažuriranje informacija u vašem indeksu softvera i instaliranje Redis biblioteke za PHP. Then, we’ll create a PHP resource that restricts access based on a user’s IP address.
Korak 2: Stvorite PHP web resurs za ograničavanje brzine
In this step, you’ll create a demo.php file in your web server’s root directory ( /var/www/html/). This file will be open to the public, and users will be able to launch the URL in their preferred web browser. Later, we’ll be using the curl command to verify the accessibility of the resource we want to use. Users can access the sample resource file three times in a 15-second span. An attempt exceeding the maximum limit will throw an error message.
This file’s primary functionality is strongly dependent on the Redis server. The PHP code in the file creates a key on the Redis server depending on the user’s IP address when the user accesses the resource for the first time. The code will attempt to match the user’s IP address with the keys saved in the Redis server and increase the value by one if the key exists when the user returns to the resource. The PHP code will keep checking to see if the new value has reached the maximum amount.
Nakon 15 sekundi, Redis ključ, koji se temelji na IP adresi korisnika, isteći će, a praćenje korisnikovih posjeta web resursu započet će ponovno. Otvorite /var/www/html/demo.php datoteku u nano uređivaču teksta:
|
1 |
sudo nano /var/www/html/demo.php |
Zatim ispunite sva polja za inicijalizaciju Redis klase. Ne zaboravite postaviti REDIS_PASSWORD na ispravnu vrijednost:
|
1 2 3 4 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); |
Redis->auth podržava autentifikaciju običnim tekstom Redis poslužitelja. To dobro funkcionira ako radite lokalno (putem localhosta), ali ako imate posla s udaljenim Redis poslužiteljem, SSL autentifikacija se preporučuje.
Zatim, u istoj datoteci, postavite sljedeće varijable na njihove zadane vrijednosti:
|
1 2 3 4 5 |
. . . $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; |
Shvatimo ove izjave detaljno:
-
$max_calls_limit: Korisnik ne može pristupiti resursu iznad ovog maksimalnog ograničenja poziva.
-
$time_period: Ovo se koristi kao vremenski okvir i računa se u sekundama. Ovdje je korisniku dopušten pristup resursu u skladu s ograničenjima postavljenim u $max_calls_limit .
-
$total_user_calls: Zbraja koliko je puta korisnik zatražio pristup poziva ograničenju u zadanom vremenskom razdoblju.
Zatim dodajte sljedeći kod kako biste dobili IP adresu onoga koji traži pristup web stranici:
|
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']; } |
Kao demonstracija, ovaj kod bilježi radnje korisnika prema njihovim IP adresama. Ako imate zaštićeni resurs na poslužitelju koji zahtijeva autentifikaciju, možete pratiti radnje korisnika pomoću njihovih korisničkih imena ili pristupnih tokena.
U našem vodiču, svakom korisniku koji se prijava u vaš sustav bit će dodijeljen jedinstveni identifikator (na primjer, ID klijenta, ID razvojnog programera, ID dobavljača ili čak ID korisnika). Ne zaboravite koristiti ove ID-ove umjesto $user_ip adrese ako pratite naš vodič.
Ovdje je IP adresa korisnika dovoljna za demonstraciju koncepta. Dodajte sljedeći blok koda u svoju datoteku nakon što dobijete IP adresu korisnika iz prethodnog isječka koda:
|
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 "Korisnik " . $user_ip_address . " ograničenje je prekoračeno."; exit(); } } echo "Dobrodošli " . $user_ip_address . " ukupno ostvarenih poziva " . $total_user_calls . " u " . $time_period . " sekundi"; |
Evo pregleda ovih naredbi:
-
if...else: Naredba provjerava postoji li ključ definiran s IP adresom na Redis poslužitelju.
-
Ako ključ nije pronađen, if (!$redis->exists($user_ip_address)) {...}, možete postaviti ključ i definirati njegovu vrijednost na 1 pomoću $redis->set($user_ip_address, 1).
-
-
$redis->expire($user_ip_address, $time_period): Određuje da ključ istekne u navedeno vrijeme. Ovdje u ovom vodiču postavili smo ga na 15 sekundi.
-
Ako korisnikova IP adresa nije pronađena u Redis ključu, postavite varijablu $total_user_calls vrijednost kao 1.
-
else {...}: Blok naredbi koristi $redis->INCR($user_ip_address); naredbu za povećanje vrijednosti Redis ključa za 1. Ovo će se primijeniti na svaku IP adresu povezanu s ključem.
-
Napomena: To možete postići samo kada je ključ već postavljen na Redis poslužitelju i računa se kao ponovljeni zahtjev.
-
-
$total_user_calls = $redis->get($user_ip_address): Ova naredba dohvaća ukupne zahtjeve provjerom njihovog odgovarajućeg ključa temeljenog na IP adresi na Redis poslužitelju.
-
if ($total_user_calls > $max_calls_limit) {... }..: Ova if naredba koristi se za provjeru prekoračenog ograničenja. Ako je prekoračeno, obavještavate korisnika s echo "Korisnik" . $user_ip_address . " je prekoračio ograničenje.";.
Naposljetku, obavještavate korisnika o njegovom broju posjeta u određenom razdoblju pomoću naredbe echo "Dobrodošli" . $user_ip_address . "ukupno upućenih poziva" . $total_user_calls . "u" . $time_period . "sekundi"; .
Nakon toga dodajte sljedeće retke koda u svoju /var/www/html/demo.php datoteku:
|
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 "User " . $user_ip_address . " limit exceeded."; exit(); } } echo "Welcome " . $user_ip_address . " total calls made " . $total_user_calls . " in " . $time_period . " seconds"; ?> |
Spremite i zatvorite /var/www/html/demo.php datoteku nakon što je uredite. Na demo.php web stranici sada ste izradili logiku potrebnu za ograničavanje učestalosti zahtjeva korisnika. Testirajmo našu skriptu u sljedećem koraku.
Korak 3: Pokretanje testa ograničavanja učestalosti u Redisu
Koristit ćete curl naredbu u ovom koraku kako biste zatražili web resurs koji ste napisali u Koraku 2. Kako biste temeljito testirali skriptu, izdajte jednu naredbu koja zahtijeva resurs pet puta. To se može postići dodavanjem zamjenskog URL argumenta u demo.php kraja datoteke. Za izvršavanje curl uputa pet puta, upotrijebite vrijednost ?[1-5] na kraju svog zahtjeva.
Izvršite sljedeću curl naredbu u nastavku:
|
1 |
curl -H "Accept: text/plain" -H "Content-Type: text/plain" -X GET http://localhost/demo.php?[1-5] |
Kada izvršite kod, trebali biste dobiti nešto poput ovoga:
|
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 Dobrodošli 127.0.0.1 ukupno poziva ostvareno 1 u 15 sekundi [2/5]: http://localhost/demo.php?2 --> <stdout> --_curl_--http://localhost/demo.php?2 Dobrodošli 127.0.0.1 ukupno poziva ostvareno 2 u 15 sekundi [3/5]: http://localhost/demo.php?3 --> <stdout> --_curl_--http://localhost/demo.php?3 Dobrodošli 127.0.0.1 ukupno poziva ostvareno 3 u 15 sekundi [4/5]: http://localhost/demo.php?4 --> <stdout> --_curl_--http://localhost/demo.php?4 Korisnik 127.0.0.1 ograničenje prekoračeno. [5/5]: http://localhost/demo.php?5 --> <stdout> --_curl_--http://localhost/demo.php?5 Korisnik 127.0.0.1 ograničenje prekoračeno. |
Prva tri zahtjeva su, kao što vidite, prošla bez problema. Četvrti i peti upit su, međutim, bili ograničeni vašom skriptom. Velika je vjerojatnost da Redis poslužitelj usporava brzinu kojom ljudi mogu slati upite.
Naveli ste niske vrijednosti za dvije varijable navedene u nastavku ovog vodiča:
|
1 2 3 4 |
... $max_calls_limit = 3; $time_period = 15; ... |
Kada izradite svoju aplikaciju u produkcijskom okruženju, možda biste trebali razmisliti o korištenju većih brojeva, ovisno o tome koliko često mislite da će je ljudi koristiti.
Dobra je ideja ispitati statistiku u stvarnom vremenu prije prilagodbe ovih brojeva. U ovom primjeru, ako zapisi vašeg poslužitelja pokazuju da prosječni korisnik posjeti vašu aplikaciju 1000 puta svakih 60 sekundi, možete upotrijebiti taj broj kao primjer koliko ograničavanja primijeniti.
Zaključak
U ovom ste vodiču naučili kako koristiti Redis poslužitelj s PHP-om na Ubuntuu 20.04. Iako ovaj članak prikazuje kako funkcionira ograničavanje brzine s Redisom, možete ga prilagoditi kako bi zadovoljio potrebe vaše web aplikacije. Potičemo vas da istražite primjere iz stvarnog svijeta poput Twitterovog maksimalnog ograničenja zahtjeva, Googleovog Custom Search JSON API-ja, i drugu sličnu dokumentaciju kako biste proširili svoje znanje o ograničavanju brzine i sami eksperimentirali koristeći različita vremenska ograničenja.
Nadalje, postoji mnogo drugih materijala za učenje o Redisu i PHP-u kojima možete pristupiti s naših blogova:
- Implementacija PHP aplikacije na Kubernetes klaster s Ubuntuom 18.04
- Instalacija i osiguravanje PHPmyadmina na Ubuntuu 20.04
- Kako instalirati LEMP stog (Linux Nginx MySQL PHP) na Ubuntuu 20.04
Sretno programiranje!
Komentari
Još nema komentara. Budite prvi.