Lançado · em melhoria
Algorithm
A limitação de taxa restringe quantas requisições um usuário ou IP pode fazer por janela de tempo: token bucket, janela deslizante, leaky bucket e Redis.
Um limitador de taxa (rate limiter) controla quantas requisições são aceitas em um período de tempo. Você define uma chave, um limite e uma janela, como "100 requisições por minuto por usuário", e o que passar disso é rejeitado ou atrasado. Os algoritmos clássicos são janela fixa, log de janela deslizante, contador de janela deslizante, token bucket e leaky bucket, e eles diferem em precisão, uso de memória e tratamento de rajadas.
Quase toda funcionalidade exposta ao mundo externo, de APIs públicas a login, pagamentos e envio de mensagens, fica atrás de um limitador de taxa. Ele protege os servidores de picos de tráfego e de loops de retentativa descontrolados, impede que um único usuário monopolize a capacidade compartilhada e desacelera ataques de força bruta. Também é um tema frequente em entrevistas de design de sistemas.
Comece escrevendo um contador de janela fixa e veja como ele deixa passar o dobro do limite na virada da janela; depois corrija isso com janela deslizante e token bucket. Em seguida, aprenda a testar com um relógio injetado, a responder HTTP 429 com Retry-After e a compartilhar um limite entre servidores com INCR, EXPIRE e scripts Lua do Redis.
Os tokens são repostos a uma taxa constante e cada requisição gasta um: a taxa média é respeitada e rajadas são permitidas até a capacidade do balde.
Um log de timestamps, ou uma mistura ponderada de dois contadores, conta as requisições recentes sem o pico na virada da janela fixa.
Limites separados por ID de usuário, chave de API, endereço IP ou endpoint impedem que um único cliente monopolize os recursos.
O INCR atômico do Redis e os scripts Lua permitem que vários servidores compartilhem um limite sem condições de corrida.
TokenBucket repõe rate tokens por segundo e guarda no máximo capacity. allow() credita de uma vez todos os tokens ganhos desde a última chamada (reposição preguiçosa) e gasta um se houver o suficiente. Ao executar, as 5 primeiras chamadas passam como rajada e as 3 seguintes são rejeitadas; depois de uma pausa de 1,1 segundo, mais duas passam. O tempo é medido com time.monotonic(), que nunca volta para trás.
token_bucket.py
import time
class TokenBucket:
"""Allow bursts of up to `capacity` requests, refilled at `rate` tokens per second."""
def __init__(self, rate: float, capacity: float) -> None:
self.rate = rate
self.capacity = capacity
self.tokens = capacity
self.updated = time.monotonic()
def allow(self, cost: float = 1.0) -> bool:
now = time.monotonic()
self.tokens = min(self.capacity, self.tokens + (now - self.updated) * self.rate)
self.updated = now
if self.tokens >= cost:
self.tokens -= cost
return True
return False
if __name__ == "__main__":
bucket = TokenBucket(rate=2, capacity=5) # 2 requests per second, bursts of 5
print([bucket.allow() for _ in range(8)]) # 5 x True, then 3 x False
time.sleep(1.1) # about 2.2 tokens come back
print(bucket.allow(), bucket.allow(), bucket.allow()) # True True False
python token_bucket.pySeis capítulos que levam você da instalação aos conceitos essenciais de Limitação de taxa.
Tire dúvidas, compartilhe experiências e troque opiniões sobre Limitação de taxa.
Ainda não há discussões. Comece a primeira.
0 comentários
Fazer login · Faça login para deixar um comentário.
Seja o primeiro a comentar.