Redis, também chamado de Remote Dictionary Server, é um banco de dados em memória de código aberto. É um sistema de armazenamento estruturado em dados que roda na RAM de um servidor, o que é muito mais rápido do que o Solid State Drive mais rápido (SSD). Como resultado, o Redis é muito responsivo e uma excelente opção para limitação de taxa.
A limitação de taxa restringe o número de vezes que um usuário pode solicitar um recurso de um servidor. Muitos serviços usam limites de taxa para impedir o abuso do serviço, como quando um usuário tenta sobrecarregar um servidor com muita carga. Por exemplo, ao usar PHP para desenvolver uma API (Application Programming Interface) pública para sua aplicação web, restrições de taxa são necessárias. Isso ocorre porque, ao expor uma API ao público, você desejará limitar quantas vezes um indivíduo pode repetir uma atividade em um determinado período de tempo. Usuários que não têm autoridade sobre seu sistema podem paralisá-lo.
A limitação de taxa permite que sua aplicação funcione sem problemas, rejeitando solicitações de usuários que excedam um limite definido. Se você tiver um grande número de clientes, a limitação de taxa impõe uma política de uso justo que permite a cada usuário acessar sua aplicação em alta velocidade. A limitação de taxa também pode ajudar a economizar dinheiro em largura de banda, reduzindo o congestionamento em seu servidor.
Ao rastrear a atividade do usuário em um banco de dados como o MySQL, seria possível criar um programa de limitação de taxa. No entanto, como esses dados devem ser baixados do disco e avaliados em relação ao limite definido, o resultado final pode não ser escalável quando várias pessoas entrarem em contato com o sistema. Isso não apenas é ineficiente, mas as soluções de gerenciamento de banco de dados relacional não foram criadas para isso.
O Redis é uma boa escolha para criar um limitador de taxa porque funciona como um banco de dados em memória e foi comprovadamente confiável para isso. Neste tutorial, guiaremos você pelas etapas de implementação de limitação de taxa em PHP usando Redis no Ubuntu 20.04.
Vamos começar!
Pré-requisitos
Para acompanhar este tutorial, você precisará do seguinte:
-
A versão mais recente do Ubuntu instalada em seu sistema.
-
Os usuários do sistema devem ter privilégios sudo.
-
Uma pilha LAMP.
-
Configure isso seguindo o Como configurar a pilha LAMP tutorial.
-
-
Um servidor Redis.
-
Acompanhe o guia Como instalar e proteger o servidor Redis para configurar o Redis em seu sistema.
-
Passo 1: Instalar a extensão Redis para PHP
Antes de começarmos, vamos atualizar os repositórios para evitar conflitos de pacotes:
|
1 |
sudo apt update |
Em seguida, instale a extensão php-redis, um pacote que torna possível usar o Redis em programas PHP. Execute o seguinte comando sudo para instalar php-redis:
|
1 |
sudo apt install -y php-redis |
Depois disso, reinicie o servidor Apache para carregar a biblioteca php-redis :
|
1 |
sudo systemctl restart apache2 |
O próximo passo é atualizar as informações no seu índice de software e instalar a biblioteca Redis para PHP. Em seguida, criaremos um recurso PHP que restringe o acesso com base no endereço IP do usuário.
Passo 2: Criar um recurso web PHP para limitação de taxa
Neste passo, você criará um arquivo demo.php no diretório raiz do seu servidor web ( /var/www/html/). Este arquivo estará aberto ao público, e os usuários poderão abrir a URL em seu navegador web preferido. Mais tarde, usaremos o comando curl para verificar a acessibilidade do recurso que queremos usar. Os usuários podem acessar o arquivo de recurso de exemplo três vezes em um intervalo de 15 segundos. Uma tentativa que exceda o limite máximo gerará uma mensagem de erro.
A funcionalidade principal deste arquivo depende fortemente do servidor Redis. O código PHP no arquivo cria uma chave no servidor Redis dependendo do endereço IP do usuário quando este acessa o recurso pela primeira vez. O código tentará corresponder o endereço IP do usuário com as chaves salvas no servidor Redis e aumentará o valor em um se a chave existir quando o usuário retornar ao recurso. O código PHP continuará verificando se o novo valor atingiu a quantidade máxima.
Após 15 segundos, a chave do Redis, que é baseada no endereço IP do usuário, expirará, e o rastreamento das visitas do usuário ao recurso web começará novamente. Abra o /var/www/html/demo.php arquivo no nano editor de texto:
|
1 |
sudo nano /var/www/html/demo.php |
Em seguida, preencha todos os campos para inicializar a classe Redis. Não se esqueça de definir o REDIS_PASSWORD para o valor correto:
|
1 2 3 4 |
<?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('REDIS_PASSWORD'); |
Redis->auth suporta autenticação em texto simples do servidor Redis. Isso funciona bem se você estiver trabalhando localmente (através do localhost), mas se estiver lidando com um servidor Redis remoto, autenticação SSL é recomendada.
Em seguida, no mesmo arquivo, defina as seguintes variáveis para seus valores padrão:
|
1 2 3 4 5 |
. . . $max_calls_limit = 3; $time_period = 15; $total_user_calls = 0; |
Vamos entender essas instruções em detalhes:
-
$max_calls_limit: Um usuário não pode acessar o recurso além deste limite máximo de chamadas.
-
$time_period: Isso é usado como um intervalo de tempo e é contado em segundos. Aqui, o usuário tem permissão para acessar o recurso de acordo com os limites definidos no $max_calls_limit .
-
$total_user_calls: Soma o número de vezes que um usuário solicitou acesso ao chamadas limite em um determinado período de tempo.
Em seguida, adicione o seguinte código para obter o endereço IP do solicitante que está pedindo para acessar a página web:
|
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']; } |
Como demonstração, este código registra as ações dos usuários por seus endereços IP. Se você tiver um recurso protegido no servidor que precise de autenticação, poderá rastrear as ações dos usuários usando seus nomes de usuário ou tokens de acesso.
Em nosso guia, cada usuário que fizer login em seu sistema receberá uma identificação exclusiva (por exemplo, um ID de cliente, ID de desenvolvedor, ID de fornecedor ou até mesmo um ID de usuário). Lembre-se de usar esses IDs em vez do $user_ip endereço se você estiver acompanhando nosso tutorial.
Aqui, o endereço IP do usuário é suficiente para demonstrar o conceito. Adicione o seguinte bloco de código ao seu arquivo assim que tiver o endereço IP do usuário do trecho de código anterior:
|
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 "Usuário " . $user_ip_address . " limite excedido."; exit(); } } echo "Bem-vindo " . $user_ip_address . " total de chamadas feitas " . $total_user_calls . " em " . $time_period . " segundos"; |
Aqui está uma visão geral destas instruções:
-
if...else: A instrução verifica se existe uma chave definida com o endereço IP no servidor Redis.
-
Se a chave não for encontrada, se (!$redis->exists($user_ip_address)) {...}, você pode definir a chave e configurar seu valor como 1 usando $redis->set($user_ip_address, 1).
-
-
$redis->expire($user_ip_address, $time_period): Faz a chave expirar em um tempo especificado. Aqui neste tutorial, nós a definimos para 15 segundos.
-
Se o endereço IP do usuário não for encontrado na chave Redis, defina o valor da variável $total_user_calls valor como 1.
-
else {...}: O bloco de instrução usa o $redis->INCR($user_ip_address); comando para incrementar o valor da chave Redis em 1. Isso será aplicado a cada endereço IP alinhado com a chave.
-
Note: Você só pode conseguir isso quando a chave já estiver definida no servidor Redis e contada como uma requisição repetitiva.
-
-
$total_user_calls = $redis->get($user_ip_address): Esta instrução recupera o total de requisições verificando sua respectiva chave baseada no endereço IP no servidor Redis.
-
if ($total_user_calls > $max_calls_limit) {... }..: Esta if instrução é usada para verificar o limite excedido. Se sim, você notifica o usuário com echo "Usuário" . $user_ip_address . " limite excedido.";.
Finalmente, você está notificando o usuário sobre o número de visitas em um período especificado usando a instrução echo "Bem-vindo" . $user_ip_address . "total de chamadas feitas" . $total_user_calls . "em" . $time_period . "segundos"; .
Depois disso, adicione as seguintes linhas de código no seu arquivo /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 "Usuário " . $user_ip_address . " limite excedido."; exit(); } } echo "Bem-vindo " . $user_ip_address . " total de chamadas feitas " . $total_user_calls . " em " . $time_period . " segundos"; ?> |
Salve e feche o arquivo /var/www/html/demo.php após terminar de modificá-lo. Na página web demo.php, você agora criou a lógica necessária para limitar a taxa de requisições dos usuários. Vamos testar nosso script na próxima etapa.
Etapa 3: Executar o teste de limitação de taxa do Redis
Você usará o comando curl nesta etapa para solicitar o recurso web que você escreveu na Etapa 2. Para testar minuciosamente o script, envie um único comando que solicite o recurso cinco vezes. Isso pode ser feito adicionando um argumento de URL placeholder ao demo.php fim do arquivo. Para realizar as curl instruções cinco vezes, use o valor ?[1-5] no final da sua requisição.
Execute o seguinte curl comando abaixo:
|
1 |
curl -H "Accept: text/plain" -H "Content-Type: text/plain" -X GET http://localhost/demo.php?[1-5] |
Quando você executar o código, deverá obter algo como isto:
|
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 Bem-vindo 127.0.0.1 total de chamadas realizadas 1 em 15 segundos [2/5]: http://localhost/demo.php?2 --> <stdout> --_curl_--http://localhost/demo.php?2 Bem-vindo 127.0.0.1 total de chamadas realizadas 2 em 15 segundos [3/5]: http://localhost/demo.php?3 --> <stdout> --_curl_--http://localhost/demo.php?3 Bem-vindo 127.0.0.1 total de chamadas realizadas 3 em 15 segundos [4/5]: http://localhost/demo.php?4 --> <stdout> --_curl_--http://localhost/demo.php?4 Usuário 127.0.0.1 limite excedido. [5/5]: http://localhost/demo.php?5 --> <stdout> --_curl_--http://localhost/demo.php?5 Usuário 127.0.0.1 limite excedido. |
As primeiras três requisições, como você pode ver, ocorreram sem problemas. As quarta e quinta consultas, no entanto, foram limitadas pelo seu script. Há uma boa chance de o servidor Redis estar diminuindo a velocidade com que as pessoas podem fazer consultas.
Você especificou valores baixos para as duas variáveis listadas abaixo neste guia:
|
1 2 3 4 |
... $max_calls_limit = 3; $time_period = 15; ... |
Ao criar seu aplicativo em um ambiente de produção, você pode querer pensar em usar números maiores, dependendo de com que frequência você acha que as pessoas o usarão.
É uma boa ideia examinar as estatísticas em tempo real antes de ajustar esses números. Neste exemplo, se os logs do seu servidor mostrarem que um usuário médio visita seu aplicativo 1.000 vezes a cada 60 segundos, você pode usar esse número como um exemplo de quanta limitação usar.
Conclusão
Neste guia, você aprendeu como utilizar um servidor Redis com PHP no Ubuntu 20.04. Embora este artigo demonstre como a limitação de taxa funciona com o Redis, você pode personalizá-lo para atender às demandas da sua aplicação web. Incentivamos você a explorar exemplos do mundo real como limite máximo de requisições do Twitter, API JSON de Pesquisa Personalizada do Google, e outras documentações semelhantes para aprimorar seu conhecimento sobre limitação de taxa e tentar experimentar por conta própria usando diferentes limites de tempo.
Além disso, existem muitos outros materiais de aprendizado sobre Redis e PHP que você pode acessar em nossos blogs:
- Implantar uma Aplicação PHP em um Cluster Kubernetes com o Ubuntu 18.04
- Instalando e Protegendo o PHPmyadmin on Ubuntu 20.04
- Como instalar a Stack LEMP (Linux Nginx MySQL PHP) no Ubuntu 20.04
Feliz Computação!
Comentários
Nenhum comentário ainda. Seja o primeiro.