Реализация Rate Limiting на уровне API Gateway
Rate Limiting защищает backend-сервисы от перегрузки и предотвращает злоупотребления API. На уровне Gateway это работает эффективнее, чем в каждом сервисе отдельно — одна точка применения политик для всего трафика.
Алгоритмы Rate Limiting
Token Bucket — ведро с токенами, пополняемое с фиксированной скоростью. Разрешает кратковременные всплески (burst). Используется в большинстве API Gateway.
Leaky Bucket — трафик вытекает с постоянной скоростью, всплески сглаживаются. Предсказуемая нагрузка на upstream.
Fixed Window — считает запросы в фиксированном временном окне. Проблема: удвоение нагрузки на границе окна.
Sliding Window — скользящее окно. Точнее Fixed Window, нет эффекта границы.
Kong: многоуровневый rate limiting
# Глобальный лимит (все сервисы)
curl -X POST http://localhost:8001/plugins \
-d "name=rate-limiting" \
-d "config.minute=1000" \
-d "config.hour=20000" \
-d "config.policy=redis" \
-d "config.redis_host=redis" \
-d "config.limit_by=ip"
# Лимит на уровне сервиса
curl -X POST http://localhost:8001/services/payments-api/plugins \
-d "name=rate-limiting" \
-d "config.second=10" \
-d "config.minute=200" \
-d "config.limit_by=consumer"
# Лимит для конкретного consumer
curl -X POST http://localhost:8001/consumers/free-tier/plugins \
-d "name=rate-limiting" \
-d "config.minute=60" \
-d "config.hour=500"
Заголовки в ответе (клиент видит лимиты):
X-RateLimit-Limit-Minute: 60
X-RateLimit-Remaining-Minute: 43
RateLimit-Reset: 37
APISIX: распределённый rate limiting
{
"plugins": {
"limit-count": {
"count": 100,
"time_window": 60,
"rejected_code": 429,
"rejected_msg": "Too many requests",
"key": "consumer_name",
"policy": "redis",
"redis_host": "redis",
"redis_port": 6379,
"redis_database": 0,
"show_limit_quota_header": true
},
"limit-req": {
"rate": 10,
"burst": 5,
"key": "remote_addr",
"rejected_code": 429
},
"limit-conn": {
"conn": 50,
"burst": 10,
"key": "remote_addr",
"rejected_code": 503
}
}
}
limit-req реализует Leaky Bucket (запросы сверх rate попадают в очередь burst, затем 429).
limit-conn ограничивает количество одновременных соединений.
AWS API Gateway: Usage Plans
resource "aws_api_gateway_usage_plan" "tiers" {
for_each = {
free = { rate = 10, burst = 5, quota = 1000, period = "DAY" }
basic = { rate = 50, burst = 25, quota = 10000, period = "DAY" }
pro = { rate = 200, burst = 100, quota = 100000, period = "DAY" }
enterprise = { rate = 1000, burst = 500, quota = 0, period = "DAY" } # без квоты
}
name = "plan-${each.key}"
api_stages {
api_id = aws_api_gateway_rest_api.main.id
stage = "prod"
}
throttle_settings {
rate_limit = each.value.rate
burst_limit = each.value.burst
}
dynamic "quota_settings" {
for_each = each.value.quota > 0 ? [1] : []
content {
limit = each.value.quota
period = each.value.period
}
}
}
Динамический rate limiting по бизнес-атрибутам
Rate limit не всегда зависит только от IP или API-ключа. Часто нужна логика: подписка пользователя, тип ресурса, время суток.
-- Kong кастомный плагин
local function get_rate_limit(consumer_id)
local cache_key = "rate:" .. consumer_id
local cached = kong.cache:get(cache_key)
if cached then return cached end
-- Запрос к billing service
local client = httpc.new()
local res = client:request_uri("http://billing-service/limits/" .. consumer_id)
local limits = cjson.decode(res.body)
kong.cache:set(cache_key, limits, 300) -- кэш 5 минут
return limits
end
local limits = get_rate_limit(consumer_id)
-- limits = { minute: 1000, hour: 10000 }
Обход rate limiting при легитимной нагрузке
Whitelist для внутренних сервисов и мониторинга:
# Kong: отключить rate limiting для определённых IP
curl -X POST http://localhost:8001/plugins \
-d "name=ip-restriction" \
-d "config.allow[]=10.0.0.0/8" \
-d "config.status=200"
# Или через consumer без rate limiting плагина
Ответ при превышении лимита
Стандартный HTTP 429 Too Many Requests с информативным телом:
{
"error": "rate_limit_exceeded",
"message": "You have exceeded the 60 requests/minute limit",
"retry_after": 23,
"limit": 60,
"window": "minute",
"upgrade_url": "https://company.com/pricing"
}
Срок выполнения
Настройка многоуровневого rate limiting (по IP, consumer, сервису) с Redis — 1–2 рабочих дня.







