Rate limiting em C++: guia completo para limitação de requisições
Rate limiting (limitação de velocidade de requisições) é um mecanismo criticamente importante para proteger servidores, APIs e sistemas distribuídos contra sobrecargas, ataques DDoS e picos aleatórios de tráfego. Em C++, a implementação de rate limiting requer algoritmos eficientes e a escolha correta de bibliotecas. Neste artigo, abordaremos as principais abordagens, bibliotecas populares e forneceremos exemplos de código prontos.
O que é rate limiting e por que é necessário?
Rate limiting estabelece o número máximo de requisições que um cliente ou sistema pode executar em um determinado intervalo de tempo. Os principais objetivos são:
- Proteção contra abusos e sobrecarga do servidor
- Garantir a distribuição uniforme de recursos entre os usuários
- Prevenção de ataques DDoS e ataques de força bruta
- Controle do consumo de cotas de API
Principais algoritmos de rate limiting
Em C++, os três algoritmos clássicos mais utilizados são:
1. Token Bucket (Balde de Tokens)
O algoritmo mais popular. Representa um "balde" com tokens que são reabastecidos a uma taxa constante. Cada requisição consome um token. Se não houver tokens, a requisição é rejeitada.
#include <chrono>#include <mutex>
class TokenBucket {private: double tokens; double maxTokens; double refillRate; // tokens por segundo std::chrono::steady_clock::time_point lastRefill; std::mutex mtx;
public: TokenBucket(double maxTokens, double refillRate) : tokens(maxTokens), maxTokens(maxTokens), refillRate(refillRate) { lastRefill = std::chrono::steady_clock::now(); }
bool tryConsume() { std::lock_guard<std::mutex> lock(mtx); refill(); if (tokens >= 1.0) { tokens -= 1.0; return true; } return false; }
private: void refill() { auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastRefill).count() / 1000.0; tokens = std::min(maxTokens, tokens + elapsed * refillRate); lastRefill = now; }};2. Leaky Bucket (Balde Furado)
As requisições entram em uma fila (balde), que é processada a uma taxa fixa. Se o balde transbordar, as requisições são descartadas.
#include <queue>#include <chrono>
class LeakyBucket {private: std::queue<int> bucket; size_t capacity; double leakRate; // requisições por segundo std::chrono::steady_clock::time_point lastLeak; std::mutex mtx;
public: LeakyBucket(size_t capacity, double leakRate) : capacity(capacity), leakRate(leakRate) { lastLeak = std::chrono::steady_clock::now(); }
bool addRequest(int request) { std::lock_guard<std::mutex> lock(mtx); leak(); if (bucket.size() < capacity) { bucket.push(request); return true; } return false; }
private: void leak() { auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastLeak).count() / 1000.0; size_t toRemove = static_cast<size_t>(elapsed * leakRate); while (toRemove > 0 && !bucket.empty()) { bucket.pop(); toRemove--; } lastLeak = now; }};3. Sliding Window Log (Janela Deslizante com Log)
Armazena os carimbos de data/hora das requisições e descarta aquelas que estão fora do limite da janela. Mais preciso, mas requer mais memória.
Bibliotecas C++ populares para rate limiting
Embora a biblioteca padrão do C++ não contenha soluções prontas, existem bibliotecas testadas:
-
Também na biblioteca
gRPC para JavaScript (Node.js): bibliotecas, configuração e exemplos de código
Agendador de tarefas em Node.js: node-cron, node-schedule e Bull
MediatR para C# (.NET): guia completo com exemplos
Agendador de Tarefas PHP: gerenciador de filas semelhante ao cron em PHP
Cliente HTTP para Kotlin: principais bibliotecas para trabalhar com rede
Recommendations