Rate Limiting en Go: guía para limitar la velocidad de las solicitudes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Rate Limiting en Go: guía completa para limitar la velocidad de las solicitudes

\n\n

Rate limiting (limitación de velocidad de solicitudes) es un mecanismo esencial de protección y gestión de carga en aplicaciones web modernas y microservicios. En el lenguaje Go (Golang), existen múltiples enfoques y bibliotecas para implementar rate limiting, desde simples hasta avanzados. En este artículo, analizaremos los conceptos principales, las bibliotecas populares y mostraremos ejemplos de código.

\n\n

¿Qué es Rate Limiting y para qué sirve?

\n\n

Rate limiting es una técnica para controlar la cantidad de solicitudes que un cliente puede enviar en un período de tiempo determinado. Los objetivos principales son:

\n\n
    \n
  • Protección contra ataques DDoS — prevenir la sobrecarga del servidor
  • \n
  • Distribución justa de recursos — acceso equitativo para todos los usuarios
  • \n
  • Ahorro de recursos — reducción de costos de infraestructura
  • \n
  • Prevención de abusos — protección contra scraping y fuerza bruta
  • \n
\n\n

Algoritmos principales de Rate Limiting

\n\n

Existen varios algoritmos clásicos, cada uno con sus ventajas:

\n\n
    \n
  • Token Bucket (Cubo de fichas) — el algoritmo más popular, donde las "fichas" se acumulan a una velocidad determinada
  • \n
  • Leaky Bucket (Cubo con fugas) — las solicitudes se procesan a una velocidad fija, el exceso se descarta
  • \n
  • Fixed Window (Ventana fija) — un contador simple de solicitudes en un intervalo de tiempo fijo
  • \n
  • Sliding Window (Ventana deslizante) — más preciso que Fixed Window, tiene en cuenta los límites de tiempo
  • \n
\n\n

Bibliotecas populares para Rate Limiting en Go

\n\n

1. Biblioteca estándar: golang.org/x/time/rate

\n\n

Esta es una extensión oficial del equipo de Go que implementa el algoritmo Token Bucket. Es ligera, fácil de usar e ideal para la mayoría de los escenarios.

\n\n
package main\n\nimport (\n    "fmt"\n    "net/http"\n    "time"\n    "golang.org/x/time/rate"\n)\n\nfunc main() {\n    // Creamos un limitador: 2 solicitudes por segundo, con burst 5\n    limiter := rate.NewLimiter(2, 5)\n\n    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {\n        if !limiter.Allow() {\n            http.Error(w, "Demasiadas solicitudes", http.StatusTooManyRequests)\n            return\n        }\n        fmt.Fprintf(w, "OK: %s", time.Now().Format(time.RFC3339))\n    })\n\n    http.ListenAndServe(":8080", nil)\n}
\n\n

2. github.com/ulule/limiter

\n\n

Una biblioteca más flexible con soporte para varios almacenes (Redis, Memcached, in-memory) y algoritmos. Adecuada para sistemas distribuidos.

\n\n
import (\n    "github.com/gin-gonic/gin"\n    "github.com/ulule/limiter/v3"\n    "github.com/ulule/limiter/v3/drivers/store/memory"\n)\n\nfunc main() {\n    // Configuración: 10 solicitudes por segundo\n    rate := limiter.Rate{\n        Period: 1 * time.Second,\n        Limit:  10,\n    }\n\n    store := memory.NewStore()\n    instance := limiter.New(store, rate)\n\n    r := gin.Default()\n    r.Use(func(c *gin.Context) {\n        key := c.ClientIP()\n        context, err := instance.Get(c.Request.Context(), key)\n        if err != nil {\n            c.AbortWithStatusJSON(500, gin.H{"error": "Error interno"})\n            return\n        }\n        if context.Reached {\n            c.AbortWithStatusJSON(429, gin.H{"error": "Demasiadas solicitudes"})\n            return\n        }\n        c.Next()\n    })\n\n    r.Run(":8080")\n}
\n\n

3. github.com/juju/ratelimit

\n\n

Una biblioteca simple y confiable de Canonical, basada en el algoritmo Token Bucket. Se caracteriza por su API minimalista.

\n\n
import (\n    "github.com/juju/ratelimit"\n    "time"\n)\n\nfunc main() {\n    // Creamos un bucket: 100 fichas, recarga de 10 fichas por segundo\n    bucket :=                    

Recommendations