Ответ
Rate Limiter (ограничитель скорости запросов) можно и нужно реализовывать на разных уровнях архитектуры, в зависимости от целей. Вот основные из них, от внешнего к внутреннему:
-
Уровень шлюза / балансировщика (API Gateway / Load Balancer)
- Где: Nginx, Kong, Traefik, AWS API Gateway.
- Зачем: Это первая линия защиты. Ограничивает трафик еще до того, как он попадет в ваши сервисы. Защищает всю инфраструктуру от DDoS-атак и всплесков трафика. Обычно настраивается по IP-адресу или API-ключу.
-
Уровень приложения (HTTP Middleware)
- Где: В коде самого приложения, как промежуточный слой для обработки HTTP-запросов. Это самый распространенный способ для бэкенд-сервисов.
- Зачем: Позволяет реализовать гибкую логику: ограничение для конкретного пользователя, эндпоинта или на основе бизнес-логики. Часто используется алгоритм "Token Bucket" (Ведро с токенами).
// Пример с использованием стандартной библиотеки golang.org/x/time/rate func RateLimit(next http.Handler) http.Handler { // 10 запросов в секунду с возможностью "всплеска" до 20 запросов limiter := rate.NewLimiter(rate.Limit(10), 20) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !limiter.Allow() { http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests) return } next.ServeHTTP(w, r) }) }
-
Распределенный Rate Limiter (Distributed Rate Limiter)
- Где: Использует внешнее хранилище, такое как Redis или Memcached.
- Зачем: Критически важен для горизонтально масштабируемых приложений. Если у вас несколько экземпляров сервиса, локальный ограничитель (как в примере выше) будет работать некорректно. Централизованное хранилище (например, Redis и его атомарные команды
INCR
,EXPIRE
) обеспечивает единый счетчик для всех экземпляров.
-
Уровень бизнес-логики
- Где: Внутри конкретной функции или метода сервиса.
- Зачем: Для ограничения специфических, ресурсоемких операций, не связанных напрямую с HTTP-запросами. Например: "не более 5 отправок SMS в час для одного пользователя" или "не более 1 генерации отчета в минуту".