Rate Limiting en Go (Golang): bibliotecas, patrones y ejemplos de implementación
Rate limiting (limitación de velocidad de solicitudes) es uno de los mecanismos clave para la protección y el control de carga en servicios web modernos y arquitectura de microservicios. En el ecosistema de Go (Golang), existen varias herramientas maduras para implementar rate limiting, desde el paquete integrado time hasta bibliotecas especializadas como golang.org/x/time/rate. En este artículo, analizaremos en detalle cómo funciona rate limiting en Go, qué bibliotecas usar y proporcionaremos ejemplos prácticos de código.
¿Qué es Rate Limiting y para qué sirve?
Rate limiting es una técnica para controlar la cantidad de solicitudes que un cliente puede realizar a un servidor en un período de tiempo determinado. Los objetivos principales son:
- Protección contra ataques DDoS — prevenir la sobrecarga del servidor.
- Distribución justa de recursos — limitar a los clientes "voraces".
- Cumplimiento de SLA — garantizar la disponibilidad para todos los usuarios.
- Ahorro de costos — reducir la carga en bases de datos y API externas.
En Go, rate limiting se implementa mediante los algoritmos Token Bucket (cubo de fichas) y Leaky Bucket (cubo con fugas). El más popular es Token Bucket.
Biblioteca golang.org/x/time/rate
La biblioteca principal y recomendada para rate limiting en Go es golang.org/x/time/rate. Implementa el algoritmo Token Bucket y forma parte del conjunto extendido de paquetes de Go (sub-repositories).
Instalación:
go get golang.org/x/time/rateComponentes principales
rate.Limiter— el objeto limitador principal.rate.NewLimiter(r rate.Limit, b int)— crea un limitador con una frecuenciarde solicitudes por segundo y un tamaño de cubob.Allow()— verifica si se puede ejecutar la solicitud ahora (no bloqueante).Wait(ctx)— bloquea la ejecución hasta que haya una ficha disponible (tiene en cuenta el contexto).Reserve()— devuelve unaReservationque permite retrasar la ejecución.
Ejemplo 1: Limitador de velocidad básico
package main
import ( "fmt" "golang.org/x/time/rate" "time")
func main() { // 2 solicitudes por segundo, cubo de 5 fichas limiter := rate.NewLimiter(2, 5)
for i := 0; i < 10; i++ { if limiter.Allow() { fmt.Printf("Solicitud %d ejecutada", i) } else { fmt.Printf("Solicitud %d rechazada (límite)", i) } time.Sleep(200 * time.Millisecond) }}Ejemplo 2: Limitador de velocidad con espera (Wait)
package main
import ( "context" "fmt" "golang.org/x/time/rate" "time")
func main() { limiter := rate.NewLimiter(1, 3) // 1 solicitud por segundo, cubo de 3 ctx := context.Background()
for i := 0; i < 6; i++ { err := limiter.Wait(ctx) if err != nil { fmt.Println("Error de espera:", err) return } fmt.Printf("Solicitud %d ejecutada a las %s", i, time.Now().Format("15:04:05.000")) }}Implementación de middleware HTTP con rate limiting
En la práctica, rate limiting se aplica con mayor frecuencia a nivel del servidor HTTP. Veamos un ejemplo de middleware para Gin o el estándar net/http.
package main
import ( "net/http" "golang.org/x/time/rate")
// RateLimiterMiddleware devuelve un middleware con límite de velocidadfunc 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 También en la biblioteca
Envío de SMS en Go (Golang): integración con API de biblioteca
Cliente OAuth para C# (.NET): implementación de autorización a través de servicios de terceros
ORM para Java: comparación de Hibernate, MyBatis y JPA con ejemplos
Apache POI Java: guía completa con ejemplos prácticos