Limitação de Taxa (Rate Limiting) no Gerenciamento de APIs
September 16, 2022
Com o desenvolvimento da internet, cada vez mais empresas começaram a adotar tecnologias nativas da nuvem e microsserviços. No entanto, devido às características técnicas dessas tecnologias, precisamos gerenciar centenas de serviços diferentes simultaneamente. Portanto, não apenas precisamos considerar o funcionamento suave de todo o sistema, mas também temos que cuidar da segurança e estabilidade de cada serviço baseado em API.
A limitação de taxa é uma das soluções mais críticas para garantir a estabilidade dos serviços baseados em API. No entanto, a aplicação se tornaria extremamente inchada se cada serviço precisasse de uma limitação de taxa. Como o ponto de entrada e saída de todo o tráfego no mundo digital, o gateway de API ajuda a alcançar a gestão unificada de todas as APIs dos serviços. Ele protege o funcionamento estável do sistema. Este artigo mostra como alcançamos a limitação de taxa através do gateway de API Apache APISIX e descreve estratégias e técnicas de limitação de taxa.
O Que É Limitação de Taxa
A limitação de taxa é uma estratégia para controlar o tráfego da internet e maximizar a taxa de transferência. Usar a limitação de taxa permite que apenas solicitações sob uma restrição específica acessem o sistema; o sistema enfileiraria qualquer solicitação adicional que exceda a restrição, reduziria suas prioridades ou até mesmo as recusaria ou abandonaria. A limitação de taxa também protege o sistema de acidentes inesperados, como picos de tráfego ou ataques maliciosos, e permite que o sistema forneça serviços consistentes e estáveis.
Por exemplo, quando um tweet viral cria um pico de tráfego, o Twitter precisa aplicar uma limitação de taxa para evitar que os servidores caiam devido à sobrecarga de tráfego.
Por Que Você Precisa Disso
Primeiro, vamos ver alguns casos de uso simples em nossa vida real que utilizam limitação de taxa. Por exemplo, atrações turísticas só podem vender um número limitado de ingressos para feriados. Além disso, geralmente precisamos reservar com antecedência ou esperar muito tempo antes de desfrutar da comida em restaurantes populares.
No gateway de API, a limitação de taxa também traz muitos benefícios. A limitação de taxa impõe algumas restrições aos nossos serviços baseados em API, garantindo seu funcionamento suave e evitando perdas desnecessárias causadas por quedas de servidores devido a picos de tráfego. Aqui listamos cinco restrições práticas diferentes:
- Limitar a taxa de solicitações.
- Limitar o número de solicitações por unidade de tempo.
- Atrasar solicitações.
- Recusar solicitações de clientes.
- Limitar a taxa de resposta.
Quando Você Precisa Disso
Junto com identificação e autenticação, a limitação de taxa pode maximizar suas vantagens e melhorar a disponibilidade do sistema das seguintes maneiras:
- Evitar ataques maliciosos.
- Garantir o funcionamento estável do sistema e evitar quedas de servidores devido a picos de tráfego.
- Evitar quedas de servidores devido a picos de solicitações causados por bugs gerados por serviços upstream ou downstream.
- Evitar chamadas de API caras com muita frequência.
- Reduzir o desperdício desnecessário de recursos, limitando a frequência das chamadas de API.
A Teoria Por Trás da Limitação de Taxa
Nas seções anteriores, apresentamos os benefícios da limitação de taxa. Nesta seção, vamos descobrir as teorias por trás disso! A implementação de baixo nível da limitação de taxa é alcançada por algoritmos específicos. Os mais comumente usados incluem:
- Algoritmo de Contador
- Janela Fixa
- Janela Deslizante
- Algoritmo do Balde Furado
- Algoritmo do Balde de Tokens
Algoritmo de Contador
Um algoritmo de contador é relativamente fácil de entender e tem dois tipos:
O primeiro tipo é o Algoritmo de Janela Fixa, que mantém um contador em uma unidade de tempo fixa e redefine o contador para zero se detectar que a unidade de tempo passou.
O segundo tipo é o Algoritmo de Janela Deslizante, que é uma melhoria baseada no primeiro; ele tem os seguintes passos:
- Divide as unidades de tempo em vários intervalos (cada um chamado de bloco).
- Cada bloco tem um contador; qualquer solicitação recebida incrementa o contador em 1.
- Após um período fixo de tempo, essa janela de tempo avança um bloco.
- Ele calcula o total de solicitações naquela janela de tempo somando todos os contadores dos blocos na janela de tempo; se o total de solicitações exceder a restrição, ele descartará todas as solicitações naquela janela de tempo.
Algoritmo do Balde Furado
Suponha que haja um balde furado; todas as solicitações seriam enfileiradas primeiro, e então o balde furado as enviaria a uma taxa constante.
Se as solicitações excederem a capacidade do balde, o sistema abandonaria e recusaria qualquer solicitação excedente. O algoritmo do balde furado pode limitar a taxa de solicitações e garantir que todas as solicitações sejam enviadas a uma taxa constante, criando um modo fácil de entrada, mas difícil de saída.
Os passos principais deste algoritmo:
- Todas as solicitações são armazenadas em um balde de tamanho fixo.
- O balde enviaria solicitações a uma taxa constante até que o balde estivesse vazio.
- Quando o balde está cheio, o sistema abandonará qualquer solicitação adicional.
Algoritmo do Balde de Tokens
O algoritmo do balde de tokens consiste em duas partes: geração e descarte de tokens. O balde de tokens gera tokens a uma taxa constante e os armazena em um balde de armazenamento fixo. Quando uma solicitação passa pelo balde de tokens, a solicitação consome um ou mais tokens. Quando o número de tokens no balde de tokens atinge a capacidade máxima, o balde de tokens abandonará novos tokens gerados. Além disso, o balde de armazenamento rejeitará solicitações recebidas se não houver tokens restantes.
Os passos principais do algoritmo do balde de tokens:
- O balde de tokens geraria tokens a uma taxa constante e os colocaria no balde de armazenamento.
- Se o balde de tokens estiver cheio, os novos tokens gerados seriam diretamente abandonados. Quando uma solicitação chega, ela consome um ou mais tokens do balde de armazenamento.
- Se não houver tokens restantes no balde de tokens, o sistema rejeitará qualquer solicitação recebida.
Alcançando Limitação de Taxa via Gateway de API
Se apenas alguns serviços baseados em API precisam ser mantidos, poderíamos usar diretamente algoritmos de limitação de taxa no serviço. Por exemplo, se você estiver usando Go para desenvolver seu sistema, ele usará tollbooth
ou golang.org/x/time/rate
para implementar os algoritmos. Se você estiver usando Lua, poderá usar os módulos limit_req
, limit_conn
e Lua-resty-limit-traffic
do NGINX para implementar os algoritmos.
Se a limitação de taxa for implementada com base em um serviço baseado em API, as restrições de limitação de taxa seriam definidas pelo próprio serviço, e cada serviço pode ter restrições diferentes. Restrições e diferenças trarão problemas de gerenciamento se o número de serviços baseados em API aumentar significativamente. Nesse caso, não poderíamos usar o gateway de API para gerenciar todos os serviços de API de forma uniforme. Você também pode implementar recursos de negócios não relacionados no gateway, como identificação, autenticação, logs, observabilidade, etc., ao usar o gateway de API para resolver problemas de limitação de taxa.
Apache APISIX é um gateway nativo da nuvem dinâmico, em tempo real e de alto desempenho. O APISIX atualmente suporta mais de 80 plugins diferentes e já construiu um ecossistema rico. Podemos gerenciar o tráfego de serviços baseados em API usando os plugins do APISIX, incluindo limit-req
, limit-conn
e limit-count
. Aqui, vou compartilhar um caso de uso para demonstrar o uso dos plugins de limitação de taxa do APISIX.
Suponha que haja um serviço baseado em API (/user/login
) que ajuda os usuários a fazer login. Para evitar ataques maliciosos e esgotamento de recursos, precisamos habilitar a função de limitação de taxa para garantir a estabilidade do sistema.
Limitar Solicitações
O plugin limit-req
limita a taxa de solicitações, usando o algoritmo do balde furado, e o vinculamos a rotas correspondentes ou clientes específicos.
Podemos usar diretamente a API Admin do APISIX para criar uma rota:
X-API-Key
é a admin_key na configuração do APISIX.
curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["POST"],
"uri": "/user/login",
"plugins": {
"limit-req": {
"rate": 3,
"burst": 2,
"rejected_code": 503,
"key": "remote_addr"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
O significado deste trecho de código: Usamos o endereço IP do cliente como requisito para limitar a taxa de solicitações.
- Se a taxa de solicitações for menor que 3 solicitações/segundo (
rate
), então a solicitação é normal; - Se a taxa de solicitações for maior que 3 solicitações/segundo e menor que 5 solicitações/segundo (
rate+burst
), iremos reduzir a prioridade dessas solicitações excedentes; - Se a taxa de solicitações for maior que 5 solicitações/segundo (
rate+burst
), qualquer solicitação que exceder a restrição máxima retornará o código HTTP 503.
Se você quiser saber mais sobre limit-req
, consulte este documento: APISIX limit-req
Limitar Conexões
O plugin limit-conn
limita solicitações paralelas (ou conexões paralelas). Aqui está um exemplo de código para habilitar este plugin para /user/login
:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["POST"],
"uri": "/user/login",
"id": 1,
"plugins": {
"limit-conn": {
"conn": 3,
"burst": 2,
"default_conn_delay": 0.1,
"rejected_code": 503,
"key": "remote_addr"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
O significado deste trecho de código: Usamos o endereço IP do cliente como requisito para limitar solicitações paralelas.
- Se as conexões paralelas do mesmo cliente forem menores que 3 (
conn
), então ele responde com o status normal 200; - Se as conexões paralelas forem maiores que 3 (
conn
) mas menores que 5 (conn+burst
), iremos atrasar as solicitações excedentes, aumentando o tempo de atraso em 0,1 segundos; - Se as conexões paralelas forem maiores que 5 (
conn+burst
), essa solicitação será recusada e retornará o código HTTP 503.
Se você quiser saber mais sobre limit-conn
, consulte este documento: APISIX limit-conn
Limitar Contagem
O plugin limit-count
é semelhante à limitação de taxa da API do Github; ele limita o número total de solicitações em um intervalo de tempo específico e retorna a contagem restante de solicitações no cabeçalho HTTP. Aqui está um exemplo de código para habilitar este plugin para /user/login
:
curl -i http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/user/login",
"plugins": {
"limit-count": {
"count": 3,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "local"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:9001": 1
}
}
}'
O significado deste trecho de código: Usamos o endereço IP do cliente como requisito para limitar o número de solicitações; o contador é salvo localmente na memória.
Se houver mais de 3 (count
) solicitações dentro de 60 segundos (time_window
), as solicitações enviadas além de 3 vezes retornarão o código HTTP 503 (rejected_code
).
Se você quiser saber mais sobre limit-count
, consulte este documento: APISIX limit-count
As Vantagens da Limitação de Taxa do Apache APISIX
Quando usamos o NGINX para gerenciar o tráfego, se o número de solicitações de API criar um pico de tráfego, o NGINX exporá suas deficiências, e uma delas é a incapacidade de carregar configurações dinamicamente. Por outro lado, os serviços do APISIX (como Rota e Serviço) podem suportar a recarga dinâmica de configurações. Mesmo que haja um pico de tráfego, o APISIX pode modificar instantaneamente a limitação de taxa e outras configurações de plugins de segurança. Graças ao mecanismo de observação do etcd, ele permite que o APISIX atualize a camada de dados em milissegundos sem recarregar os serviços.
Além disso, o APISIX também suporta limitação de taxa em nível de cluster. Por exemplo, podemos usar limit-count
para modificar a configuração de policy
para redis
ou redis-cluster
. Assim, podemos limitar as taxas em nível de cluster compartilhando resultados de computação entre diferentes nós do APISIX.
Como um DevOps, usar um painel gráfico para gerenciar todos os serviços de API aumentaria a produtividade. O APISIX fornece um painel de gerenciamento visual para tornar a modificação de configurações de API muito mais conveniente.
Conclusão
Limitação de taxa é uma necessidade comum em cenários de negócios reais e é uma maneira crucial de proteger o sistema de picos de tráfego e garantir seu funcionamento suave. A limitação de taxa é apenas uma parte do gerenciamento de serviços de API; também podemos usar muitas outras tecnologias para fornecer suporte de segurança vital e melhorar a experiência do usuário.