Projetar rate limiter 'ov
1) Por que rate limiting
Rate limiting protege a disponibilidade e a economia da API: interrompe floods, «burst» retraes, credential stuffing, protege transações caras (transações em dinheiro, geração de relatórios), suaviza a pressão sobre sistemas dependentes (BD/provedores). Bom design dá justiça (fairness), previsibilidade de latidão e claro SLO.
Alvos-chave
Estabilidade do RPS e proteção do backand contra sobrecarga.
«Elasticidade» controlada (burst allowance).
Diferenciar clientes (para-usuário/para-organização/para-chave/para-IP/para-região).
«preços» diferentes para diferentes operações.
2) Tipos de limite
Limites RPS: consultas por segundo/minuto.
Quotas: orçamento total no período (dia/mês).
Competição: operações simultâneas (checkout, heavy job).
Velocidade/faixa: bytes/segundos (download/descarga).
Limites ponderados: «custo» de uma solicitação de complexidade (por exemplo, GraphQL complexity, tamanho batch).
Adaptativos: endurece com anomalias (atividade suspeita/erro 401/403/5xx).
3) Algoritmos e quando aplicá-los
3. 1 Fixed window counter
Simples: contador por intervalo (por exemplo, 100 r/min).
Os benefícios são o valor mínimo. Contras, «burst» nos limites da janela.
Quando: painéis de almirante, baixa precisão, baixo custo.
3. 2 Sliding window (log / counter)
O Jobs armazena marcas de tempo das últimas solicitações, exatas, de memória.
Counter: média de duas janelas vizinhas (rolling), comprometimento de precisão e preço.
Quando: API público de tráfego médio, precisa de fluidez sem matemática complexa.
3. 3 Token bucket
Opções: velocidade 'r' (tokens/segundos) e capacidade 'b' (burst). Cada pedido «queima» o token.
Benefícios: natural burst allowance, simples implementação. Contras: Não há uniformidade.
Quando: Quase sempre para RPS, se for necessário «disparar» dentro de «b».
3. 4 Leaky bucket (drip)
Uma fila que «arrasta» em velocidade fixa.
Os benefícios são um fluxo de saída simples. Contras, mais atrasos.
Quando: suavização para provedores «frágeis» externos.
3. 5 GCRA (Generalized Cell Rate Algorithm)
Modelo de hora de chegada teórica (TAT):- 'TAT _ next = max (TAT _ current, now) + 1/r', pedido aceito se 'now <= TAT _ current + burst/r'.
- Vantagens: rigorosa, precisa, pouca memória (a chave é TAT). Contras, mais difícil de entender.
Quando: precisa de controle rigoroso e fluidez, limites distribuídos.
3. 6 Semaforas competitivas
Contador de Operações Ativas; entrada - se houver «bilhetes»; a saída é a libertação.
Quando: transações long-running, fluxos, WebSocket, downloads.
4) Modelo de chaves de limite
Chave = combinação de atributos:- `client_id`/`api_key`/`user_id`/`org_id`
- 'IP/ASN/geo' (proteção bruta)
- 'endpoint/method' (rotas quentes)
- 'scope/place/tier' (monetização)
- 'idempotency _ key' (operação write)
- Use a hierarquia, primeiro para-chave, depois para-organização, depois para-organização global.
5) Peso da consulta (vale-modelo)
Defina o «custo» de «q»:- GraphQL: complexidade em campos x profundidade.
- REST: tamanho da resposta/consulta, tipo de operação (read = 1, write = 3, relatório = 10).
- Batch: `cost = min(n, cap)`.
- Limitamos os tokens, não os «pedidos»: 'budget - = cost (q)'.
6) Implementação distribuída
6. 1 Armazenamento
In-processs: ultra-rápido, mas não limite total (adequado para limites «macios» locais).
O Redis é um padrão de facto. INCR/EXPIRE, Script Lua (atômica), ZSET para sliding window, chaves com TTL.
Envoy/NGINX/Kong/Traefik: filtros incorporados; confortável para o perímetro.
Serviço Mesh: limites locais para sidecar + sincronização global.
6. 2 Atômicas e corridas
Lua em Redis: verificação e incorporação a um passo.
GCRA: Armazenar um TAT com CAS/script.
Coerência do relógio: NTP, monótonos.
Sharding: hash consistente por chave; Evite os chardes quentes.
6. 3 Distribuição geográfica
Limites locais em clusters regionais + global superior (coasse).
CRDT/replicação - cuidado (atrasos, consumo duplo). Preferimos limites regionais com reservas.
7) Políticas e priorização
Planos: Free/Pro/Enterprise com diferentes 'r', 'b', quotas.
Prioridades: As rotas «caras» recebem um limite menor ou um custo maior.
Listas: allow-list para integrações, deny por ASN/proxy/TOR.
Escalação: Quando ultrapassar novamente - Baixando o limite, introduzindo proof-of-work/kupchu/challengs.
8) Exemplos de configs
8. 1 Envoy (HTTP rate limit filter, pseudo)
yaml rate_limit:
domain: public-api descriptors:
- key: api_key rate_limit:
unit: second requests_per_unit: 50 burst: 100
- key: api_key value: payments. write rate_limit:
unit: second requests_per_unit: 5 burst: 10
8. 2 NGINX (lua + Redis, pseudo)
nginx lua_shared_dict limits 10m;
location /api/ {
access_by_lua_block {
local key = ngx. var. arg_apikey.. ":".. ngx. var. request_method.. ":".. ngx. var. uri
-- token bucket in Redis (evalsha)
local allowed, retry_after = ratelimit_allow(key, 50, 100) -- r=50/s, b=100 if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}
proxy_pass http://backend;
}
8. 3 Limites competitivos (pseudocode)
pseudo on_request_start(key):
if redis. incr_with_ttl("sem:" + key, ttl=60) > MAX_CONCURRENCY:
redis. decr("sem:" + key); reject(429)
on_request_finish(key):
redis. decr("sem:" + key)
8. 4 GCRA (pseudocode)
pseudo params: r tokens/sec, burst b tat = redis. get(key) or now allowed_time = tat - (b / r)
if now < allowed_time: reject(429, retry_after = allowed_time - now)
tat_next = max(tat, now) + 1/r redis. set(key, tat_next, ttl = ceil(b/r) + safety)
9) Integração com retrações, temporizadores e circuito breaker
Retry-budget: Limite a proporção de retais a X% do tráfego principal.
Jitter: Ao backoff, adicione sempre um jitter - reduz os destaques sincronizados.
Circuito breaker: Em caso de erro elevado ('5xx', timeouts), reduza os limites ou transfira parte das rotas para 'read-only'.
Hedging: com cuidado; leve em conta o custo para não dobrar o consumo de orçamento.
10) Observabilidade e controle
Метрики: `rps_allowed`, `rps_blocked`, `429_rate`, `retry_after_avg`, `burst_used`, `quota_remaining`, `active_concurrency`.
Editoras, pela chave do limite, região, endpoint, plano.
Logs de solução (samplicados): causa de falha, contadores atuais, chave TTL.
Dashboards, cartões térmicos para chaves/endpoentes, clientes quentes.
Alerts: crescimento 429> 2-5% em rotas críticas, frequentes «esgotamentos» de quotas, desequilíbrio de chardes.
11) Testes e validação
Testes de política contratual (tabelas «se»).
Cargas: bursts (x10 de r), plateias longas, patters «sujos» (slow-POST, longas conexões).
Tráfego Chaos: fluxo desigual, clock drivt, queda Redis/mesh.
A/B-inclusão: canary rollout limites, shadow-solução (mas não bloqueamos) antes de ativar.
12) Mala Edge e sutileza
Clock skew: Use 'now ()' a partir de uma única origem (servidor) e não dos cabeçalhos do cliente.
Idempotency-Key: para write - reduz amplificação em retraias.
Operações Batch: Limite o tamanho do batch e o valor total.
Long-poll/WebSocket: Limite o número de canais/assinaturas e a duração.
Cold start: início «quente» dos contadores/pré-sal; senão, os destaques são falsos 429.
Pedidos computadoramente caros: limite até a lógica de negócios.
Limites TTL: TTL chaves deve cobrir janela + reserva (safety margin).
13) Escalada antibot
Estágios: aviso → 429 + 'Retry-After' → challange (capcha/puzzle) → unidade temporária.
Sinais: device-fingerprint, comportamento do cursor/timing, TOR/proxy/hospedagem.
Os políticos devem ser determinados e reproduzidos para os forenseiros.
14) Segurança e complacência
Deny-by-default em rotas críticas (write/finanças).
Auditoria: Mantenha as soluções de limites para as malas regulatórias e para a análise de incidentes.
PII: As chaves de limite não devem revelar dados pessoais nos logs.
15) Folha de cheque pró-prontidão
- São definidas as chaves de limite e o modelo de custo.
- O algoritmo selecionado (tocen bucket/GCRA) e o armazenamento (Redis/gateway).
- Políticas para tier's clientes + 'fusíveis' globais.
- Limites competitivos para operações longas.
- Retry-boodget, backoff com jitter, integração com circuito breaker.
- Dashboards/alertas, logs de soluções sampleados.
- Ativação Canary e modo shadow.
- Testes de bursta, platô de longa duração, falhas Redis, clock skew.
- Documentação para clientes: códigos 429, 'Retry-After', exemplos de backoff exponencial.
16) TL; DR
Use token bucket ou GCRA com Redis/passarela, projete chaves de limite e custos de consulta, adicione semafores competitivos para operações longas, integre-se com retry-budget e circuito breaker, observe 429 e «burst-capacidade», espalhe os limites através do canary/shadow e obrigatoriamente teste os burstas e falha de armazenamento.