Rate Limiting em Go (Golang): bibliotecas, padrões e exemplos de implementação
Rate limiting (limitação de velocidade de requisições) é um dos principais mecanismos de proteção e controle de carga em serviços web modernos e arquitetura de microsserviços. No ecossistema Go (Golang), existem várias ferramentas maduras para implementar rate limiting, desde o pacote integrado time até bibliotecas especializadas, como golang.org/x/time/rate. Neste artigo, vamos detalhar como o rate limiting funciona em Go, quais bibliotecas usar e fornecer exemplos práticos de código.
O que é Rate Limiting e para que serve?
Rate limiting é uma técnica para controlar o número de requisições que um cliente pode fazer a um servidor em um determinado período de tempo. Os principais objetivos são:
- Proteção contra ataques DDoS — prevenir sobrecarga do servidor.
- Distribuição justa de recursos — limitar clientes "gulosos".
- Cumprimento de SLA — garantir disponibilidade para todos os usuários.
- Economia de custos — reduzir a carga em bancos de dados e APIs externas.
Em Go, o rate limiting é implementado usando os algoritmos Token Bucket (balde de tokens) e Leaky Bucket (balde furado). O mais popular é o Token Bucket.
Biblioteca golang.org/x/time/rate
A principal e recomendada biblioteca para rate limiting em Go é golang.org/x/time/rate. Ela implementa o algoritmo Token Bucket e faz parte do conjunto estendido de pacotes Go (sub-repositories).
Instalação:
go get golang.org/x/time/rateComponentes principais
rate.Limiter— o objeto limitador principal.rate.NewLimiter(r rate.Limit, b int)— cria um limitador com taxarde requisições por segundo e tamanho de baldeb.Allow()— verifica se a requisição pode ser executada agora (não bloqueante).Wait(ctx)— bloqueia a execução até que um token esteja disponível (considera o contexto).Reserve()— retorna umaReservation, permitindo adiar a execução.
Exemplo 1: Rate limiter básico
package main
import ( "fmt" "golang.org/x/time/rate" "time")
func main() { // 2 requisições por segundo, balde de 5 tokens limiter := rate.NewLimiter(2, 5)
for i := 0; i < 10; i++ { if limiter.Allow() { fmt.Printf("Requisição %d executada", i) } else { fmt.Printf("Requisição %d rejeitada (limite)", i) } time.Sleep(200 * time.Millisecond) }}Exemplo 2: Rate limiter com espera (Wait)
package main
import ( "context" "fmt" "golang.org/x/time/rate" "time")
func main() { limiter := rate.NewLimiter(1, 3) // 1 requisição por segundo, balde de 3 ctx := context.Background()
for i := 0; i < 6; i++ { err := limiter.Wait(ctx) if err != nil { fmt.Println("Erro de espera:", err) return } fmt.Printf("Requisição %d executada em %s", i, time.Now().Format("15:04:05.000")) }}Implementação de HTTP middleware com rate limiting
Na prática, o rate limiting é mais frequentemente aplicado no nível do servidor HTTP. Vejamos um exemplo de middleware para Gin ou net/http padrão.
package main
import ( "net/http" "golang.org/x/time/rate")
// RateLimiterMiddleware retorna um middleware com rate limitfunc RateLimiterMiddleware(r rate.Limit, b int) func(http.Handler) http.Handler { limiter := rate.NewLimiter(r, b) return func(next http.Handler) http.Handler { return http.HandlerFunc(f Também na biblioteca
Cliente HTTP para Java: as principais bibliotecas para trabalhar com HTTP
Ktor Client Kotlin: guia completo com exemplos práticos
clinic.js — Monitoramento de aplicações TypeScript
Monitoramento de aplicações Rust com a biblioteca tracing