Rate Limiting en Go (Golang): bibliotecas, patrones y ejemplos de implementación

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 (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/rate


Componentes principales

  • rate.Limiter — el objeto limitador principal.
  • rate.NewLimiter(r rate.Limit, b int) — crea un limitador con una frecuencia r de solicitudes por segundo y un tamaño de cubo b.
  • 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 una Reservation que 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

Recommendations