Реалізація 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 робочих дні.







