Rate Limiting em Rust: bibliotecas para controle de requisições

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Rate Limiting em Rust: gerenciamento eficiente de carga

Rate limiting (limitação de frequência de requisições) é um mecanismo essencial para proteger e otimizar serviços web, APIs e aplicações de rede. No ecossistema Rust, existem várias bibliotecas maduras que implementam diferentes algoritmos: desde o clássico token bucket até métodos adaptativos modernos. Neste artigo, vamos explorar três bibliotecas principais: governor, leaky-bucket e ratelimit, com exemplos de código e recomendações de uso.

1. Biblioteca governor — o padrão ouro

governor é a biblioteca mais popular e flexível para rate limiting. Ela implementa o algoritmo Generic Cell Rate Algorithm (GCRA), que garante limites precisos com latência mínima. Suporta modos síncrono e assíncrono, além de middleware para Actix-web, Axum e Rocket.

Exemplo básico com governor

use governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};
use std::num::NonZeroU32;
use std::time::Duration;

fn main() {
    // Permite 5 requisições por segundo
    let quota = Quota::per_second(NonZeroU32::new(5).unwrap());
    let limiter = RateLimiter::direct(quota);

    for i in 0..10 {
        match limiter.check() {
            Ok(_) => println!("Requisição {} permitida", i),
            Err(_) => println!("Requisição {} negada (rate limit)", i),
        }
        std::thread::sleep(Duration::from_millis(100));
    }
}

Versão assíncrona com espera

use governor::{Quota, RateLimiter};
use std::num::NonZeroU32;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    let limiter = RateLimiter::direct(Quota::per_second(
        NonZeroU32::new(2).unwrap(),
    ));

    for i in 0..5 {
        limiter.until_ready().await;
        println("Requisição {} processada", i);
        sleep(Duration::from_millis(300)).await;
    }
}

Principais recursos do governor:

  • Suporte a limites por chave (por IP, por usuário) via KeyedRateLimiter
  • Integração com middleware tower para servidores HTTP
  • Estratégias configuráveis: esperar, rejeitar, desacelerar adaptativamente
  • Consumo mínimo de memória (um contador atômico por limitador)

2. Biblioteca leaky-bucket — simplicidade e confiabilidade

leaky-bucket implementa o clássico algoritmo do "balde furado". É ideal para suavizar picos de carga, garantindo um fluxo uniforme de requisições. A biblioteca é leve e não requer dependências externas.

Exemplo com leaky-bucket

use leaky_bucket::RateLimiter;
use std::time::Duration;

#[tokio::main]
async fn main() {
    let limiter = RateLimiter::builder()
        .initial(10)        // saldo inicial de tokens
        .interval(Duration::from_secs(1))  // intervalo de recarga
        .refill(5)          // quantos tokens adicionar por intervalo
        .max(20)            // número máximo de tokens
        .build();

    for i in 0..15 {
        limiter.acquire_one().await;
        println!("Requisição {} concluída", i);
    }
}

Características do leaky-bucket:

  • Suporte a API assíncrona e bloqueante
  • Possibilidade de configurar modo "burst" (picos curtos de requisições)
  • Liberação automática de tokens durante períodos de inatividade

3. Biblioteca ratelimit — abordagem minimalista

ratelimit é a biblioteca mais simples, implementando uma janela deslizante com intervalos fixos. Adequada para cenários simples onde não é necessária alta precisão.

Exemplo com ratelimit

use ratelimit::Ratelimiter;
use std::time::Duration;

fn main() {
    let mut limiter = Ratelimiter::builder(10, Duration::from_secs(1))
        .build()
        .unwrap();

    for i in 0..20 {
        if limiter.try_wait() {

Recommendations