Rate Limiting в Go: руководство по ограничению скорости запросов

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Rate Limiting в Go: полное руководство по ограничению скорости запросов

Rate limiting (ограничение скорости запросов) — это важнейший механизм защиты и управления нагрузкой в современных веб-приложениях и микросервисах. В языке Go (Golang) существует множество подходов и библиотек для реализации rate limiting, от простых до продвинутых. В этой статье мы разберем основные концепции, популярные библиотеки и покажем примеры кода.

Что такое Rate Limiting и зачем он нужен?

Rate limiting — это техника контроля количества запросов, которые клиент может отправить за определенный промежуток времени. Основные цели:

  • Защита от DDoS-атак — предотвращение перегрузки сервера
  • Справедливое распределение ресурсов — равный доступ для всех пользователей
  • Экономия ресурсов — снижение затрат на инфраструктуру
  • Предотвращение злоупотреблений — защита от скрапинга и брутфорса

Основные алгоритмы Rate Limiting

Существует несколько классических алгоритмов, каждый со своими преимуществами:

  • Token Bucket (Токен-ведро) — самый популярный алгоритм, где "токены" накапливаются с определенной скоростью
  • Leaky Bucket (Дырявое ведро) — запросы обрабатываются с фиксированной скоростью, избыток отбрасывается
  • Fixed Window (Фиксированное окно) — простой счетчик запросов за фиксированный интервал времени
  • Sliding Window (Скользящее окно) — более точный, чем Fixed Window, учитывает временные границы

Популярные библиотеки для Rate Limiting в Go

1. Стандартная библиотека: golang.org/x/time/rate

Это официальное расширение от команды Go, реализующее алгоритм Token Bucket. Она легковесна, проста в использовании и идеально подходит для большинства сценариев.

package main

import (
    "fmt"
    "net/http"
    "time"
    "golang.org/x/time/rate"
)

func main() {
    // Создаем лимитер: 2 запроса в секунду, с burst 5
    limiter := rate.NewLimiter(2, 5)

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if !limiter.Allow() {
            http.Error(w, "Слишком много запросов", http.StatusTooManyRequests)
            return
        }
        fmt.Fprintf(w, "OK: %s", time.Now().Format(time.RFC3339))
    })

    http.ListenAndServe(":8080", nil)
}

2. github.com/ulule/limiter

Более гибкая библиотека с поддержкой различных хранилищ (Redis, Memcached, in-memory) и алгоритмов. Подходит для распределенных систем.

import (
    "github.com/gin-gonic/gin"
    "github.com/ulule/limiter/v3"
    "github.com/ulule/limiter/v3/drivers/store/memory"
)

func main() {
    // Настройка: 10 запросов в секунду
    rate := limiter.Rate{
        Period: 1 * time.Second,
        Limit:  10,
    }

    store := memory.NewStore()
    instance := limiter.New(store, rate)

    r := gin.Default()
    r.Use(func(c *gin.Context) {
        key := c.ClientIP()
        context, err := instance.Get(c.Request.Context(), key)
        if err != nil {
            c.AbortWithStatusJSON(500, gin.H{"error": "Internal error"})
            return
        }
        if context.Reached {
            c.AbortWithStatusJSON(429, gin.H{"error": "Too many requests"})
            return
        }
        c.Next()
    })

    r.Run(":8080")
}

3. github.com/juju/ratelimit

Простая и надежная библиотека от Canonical, основанная на алгоритме Token Bucket. Отличается минималистичным API.

import (
    "github.com/juju/ratelimit"
    "time"
)

func main() {
    // Создаем bucket: 100 токенов, пополнение 10 токенов в секунду
    bucket := ratelimit.NewBucketWithRate(10, 100)

    for i := 0; i < 200; i++ {
        if bucket.TakeAvailable(1) > 0 {
            fmt.Println("Запрос выполнен:", i)
        } else {
            fmt.Println("Превышен лимит:", i)
            time.Sleep(100 * time.Millisecond)
        }
    }
}

Продвинутые сценарии использования

Rate Limiting с Redis для распределенных систем

Когда у вас несколько инстансов приложения, необходимо централизованное хранилище. Redis идеально подходит для этой задачи.

import (
    "github.com/go-redis/redis/v8"
    "github.com/ulule/limiter/v3/drivers/store/redis"
)                    

Рекомендаций