Як лімітувати запити: вичерпний посібник
Обмеження частоти запитів зменшує їхню кількість, захищаючи сервер від перевантаження за високого трафіку. Це як установити обмеження швидкості, щоб ніхто не міг одночасно засипати застосунок надто великою кількістю викликів. Так я можу підтримувати стабільність і забезпечувати справедливий досвід для кожного користувача.
У цій статті я розгляну кілька способів обмеження частоти запитів, поясню, як їх реалізувати, і покажу, чому вони важливі в сучасній розробці програмного забезпечення та вебскрапінг.
Навіщо лімітувати запити?
Перш ніж розглядати, як обмежувати частоту запитів, важливо зрозуміти, чому це необхідно. Серед основних причин:
- Server Load Management: Коли запитів надходить занадто багато й надто швидко, сервер може перевантажитися та погіршити швидкодію для користувачів.
- Fair Usage: Важливо забезпечити, щоб усі користувачі отримували справедливу частку ресурсів сервера. Без лімітування кілька клієнтів можуть монополізувати ресурси, що призведе до несправедливого розподілу.
- Preventing Abuse: Зловмисники можуть зловживати API, надсилаючи надмірну кількість запитів навмисно або ненавмисно. Обмеження частоти допомагає запобігати такій зловживальній поведінці.
- Cost Management: Для сервісів, де оплата залежить від кількості запитів (як-от у багатьох хмарних платформах), обмеження частоти допомагає зменшити витрати, контролюючи частоту запитів.
Automated Solutions
Якщо вашим кейсом є вебскрапінг, використання одного з цих інструментів автоматизує для вас увесь процес лімітування, тож вам не доведеться нічого робити:
- Bright Data: Потужний вебскрапінг на основі проксі для складних завдань.
- ScraperAPI: Доступна багатомовна підтримка для незахищених сайтів.
- Oxylabs: Високоякісні проксі, парсинг даних на основі ШІ.
- ScrapingBee: Справляється зі складними сайтами завдяки розв'язанню CAPTCHA.
Я не пов’язаний із жодним із постачальників; це просто інструменти, якими я та моя команда часто користуємося.
Основні поняття лімітування запитів
Обмеження частоти запитів можна реалізувати на різних рівнях: на боці клієнта (перед надсиланням запитів) і на боці сервера (під час оброблення запитів). Існує кілька популярних підходів до обмеження частоти запитів:
- Rate Limiting: Дозволяє фіксовану кількість запитів за певний період.
- Leaky Bucket Algorithm: Обмеження швидкості обробки запитів.
- Token Bucket Algorithm: Надання клієнтам токенів, що дозволяють їм виконувати запити.
- Exponential Backoff: Експоненційно сповільнює темп запитів, щоб зменшити навантаження на сервер.
Кожен метод має свої сильні сторони залежно від сценарію використання та архітектури сервісу.
Rate Limiting
Rate Limiting є найпростішою та найпоширенішою формою обмеження частоти запитів. Вона обмежує кількість запитів, які можна зробити протягом певного часового вікна.
Наприклад, якщо API дозволяє лише 100 запитів на хвилину для кожного клієнта, обмежувач частоти запитів відхилятиме запити, що перевищують цей ліміт, доки не почнеться наступна хвилина.
Implementation: This technique often uses middleware or built-in functionalities of frameworks such as Flask or Express.js.
from flask import Flask, request
from time import time
app = Flask(__name__)
rate_limit_window = 60 # 60 seconds
max_requests = 100
user_requests = {}
@app.route('/api')
def my_api():
current_time = time()
user_ip = request.remote_addr
if user_ip not in user_requests:
user_requests[user_ip] = []
# Remove outdated requests
user_requests[user_ip] = [req for req in user_requests[user_ip] if current_time - req < rate_limit_window]
if len(user_requests[user_ip]) >= max_requests:
return «Занадто багато запитів, спробуйте ще раз пізніше.», 429
# Record new request
user_requests[user_ip].append(current_time)
return "Hello, World!"
У наведеному вище прикладі лімітер частоти запитів зі ковзним вікном гарантує, що користувачі не перевищать ліміт у 100 запитів за 60-секундне вікно.
Leaky Bucket Algorithm
Алгоритм «протікаючого відра» Це ще один популярний підхід до обмеження частоти запитів. Уявіть відро з отвором у дні. Воду наливають у відро, і вона безперервно витікає. Коли відро повне, будь-яка додаткова вода переллється.
Під час тротлінгу запитів бакет заповнюється вхідними запитами, а сервер обробляє їх із фіксованою швидкістю. Якщо швидкість надходження запитів перевищує швидкість, яку сервер може обробити, надлишкові запити буде відкинуто.
Цей підхід допомагає згладжувати раптові сплески запитів і підтримує стабільне навантаження на сервер під час обробки.
Implementation: Алгоритм Leaky Bucket може ставити запити в чергу та обробляти їх рівномірно.
import queue
import threading
import time
leaky_bucket = queue.Queue(maxsize=10) # Limit the number of items that can be queued
def process_request():
while True:
request = leaky_bucket.get()
if request is None:
break
print(f"Processing request {request}")
time.sleep(1) # Simulate processing time
leaky_bucket.task_done()
# Worker thread to process requests
threading.Thread(target=process_request, daemon=True).start()
# Adding requests to the bucket
for i in range(20):
if not leaky_bucket.full():
leaky_bucket.put(f"Request {i}")
else:
print(f"Request {i} було відхилено через обмеження частоти")
Ця реалізація дозволяє сплески запитів, коли токени доступні, що може бути корисним у сценаріях, де потрібно коректно обробляти тимчасові піки попиту.
Exponential Backoff
Exponential Backoff є ще одним підходом до обмеження частоти запитів, який часто використовують для обробки повторних спроб API. Замість безперервного надсилання запитів клієнт збільшує затримку між наступними повторними спробами. Це допомагає запобігти перевантаженню сервера під час пікового навантаження.
Use Case: Його часто використовують, коли сервіс тимчасово повертає помилку “Too Many Requests” (HTTP 429) або подібну.
import time
def exponential_backoff():
attempt = 0
max_attempts = 5
while attempt < max_attempts:
try:
# Simulate API call
print(f"Attempt {attempt + 1}")
raise Exception("Перевищено ліміт API")
except Exception as e:
print(e)
attempt += 1
delay = 2 ** спроба
print(f"Повторна спроба через {delay} seconds…\"")
time.sleep(delay)
# Call the function
exponential_backoff()
Експоненційна затримка повтору тут забезпечує, що після кожного збою запити стають рідшими, зрештою даючи серверу трохи перепочинку.
Обмеження частоти на боці сервера vs. на боці клієнта
Хоч наведені вище техніки переважно демонструють лімітування на стороні сервера, важливо врахувати обмеження частоти на боці клієнта.
Client-Side Throttling
Клієнтський тротлінг допомагає керувати кількістю запитів, які клієнт надсилає ще до того, як вони дійдуть до сервера. Це допомагає уникнути помилок відмови в обслуговуванні ще до їх виникнення.
Наприклад, JavaScript-клієнт, який викликає публічний API, може реалізувати обмеження частоти запитів, щоб браузер користувача не перевантажував кінцеву точку API.
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function () {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function () {
if (Date.now() - lastRan >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
// Example usage
const makeApiCall = () => console.log("API request sent");
window.addEventListener("resize", throttle(makeApiCall, 2000));
Наведений вище JavaScript-код визначає функцію для обмеження частоти, яка зменшує кількість запусків API-запиту у відповідь на подію на кшталт зміни розміру вікна.
Популярні інструменти та фреймворки
Nginx Rate Limiting
Nginx is a popular web server with built-in capabilities to handle rate limiting using the limit_req_zone directive. This helps to throttle requests at the web server level before they even reach the application layer.
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
server {
location /api {
limit_req zone=one burst=10 nodelay;
proxy_pass http://backend_server;
}
}
}
WS API Gateway
AWS API Gateway також має вбудовані можливості обмеження частоти запитів до кінцевих точок, якими він керує, допомагаючи розробникам контролювати використання та запобігати зловживанням.
Найкращі практики обмеження частоти запитів
- Graceful Error Handling: Clients should gracefully handle errors, particularly those related to throttling (e.g., HTTP status code 429). Implementing retry logic with exponential backoff is often a good idea.
- Dynamic Throttling: Регулюйте ліміти тротлінгу залежно від доступності ресурсів або часу доби. Наприклад, знижуйте ліміти в пікові години, щоб забезпечити стабільну швидкодію для користувачів.
- Моніторинг та сповіщення: Завжди відстежуйте обсяги запитів і налаштовуйте сповіщення про підозрілі сплески, які можуть вказувати на потенційне зловживання або некоректну конфігурацію в клієнтських застосунках.
- Обмеження на рівні користувача та IP-адреси: Реалізуйте різні типи обмежень частоти запитів, наприклад на рівні користувача та за IP-адресою, щоб краще контролювати потік запитів через кілька точок доступу.
Conclusion
Тротлінг запитів є ключовим компонентом керування й підтримання надійності та стабільності вебсервісів. Такі техніки, як обмеження частоти, leaky bucket, token bucket і exponential backoff, мають свої сильні сторони, тож підходять для різних сценаріїв. Упроваджуючи тротлінг запитів як на боці клієнта, так і на боці сервера, розробники можуть ефективно захистити свої API від надмірного використання, зловживань і можливих збоїв.
Ретельно поєднуючи ці стратегії та застосовуючи їх відповідно до конкретних сценаріїв використання, розробники можуть створювати надійні, масштабовані й ефективні вебзастосунки, стійкі до навантажень.

