Ограничение скорости – это важнейший метод, используемый при разработке программного обеспечения для контроля скорости, с которой клиенты могут отправлять запросы к API или веб-службе. Это помогает предотвратить злоупотребления, обеспечивает справедливое использование и поддерживает стабильность и производительность системы. В этой статье блога мы рассмотрим различные методы и приемы реализации ограничения скорости в ваших приложениях, используя разговорный язык и предоставляя примеры кода, чтобы вам было легче его понять и реализовать.
- Ограничение фиксированной ставки окна:
Одним из самых простых методов ограничения скорости является подход с фиксированным окном. В этом методе вы разрешаете фиксированное количество запросов в течение определенного временного окна. Например, вы можете разрешить 100 запросов в минуту. После достижения лимита дальнейшие запросы отклоняются до начала следующей минуты. Вот пример того, как это можно реализовать в Node.js:
const express = require('express');
const app = express();
const MAX_REQUESTS = 100;
const WINDOW_DURATION = 60 * 1000; // 1 minute
let requestCount = 0;
let windowStart = Date.now();
app.use((req, res, next) => {
const now = Date.now();
if (now - windowStart >= WINDOW_DURATION) {
// Reset the window
windowStart = now;
requestCount = 0;
}
if (requestCount >= MAX_REQUESTS) {
return res.status(429).json({ error: 'Rate limit exceeded' });
}
requestCount++;
next();
});
// Your API routes here
app.listen(3000, () => {
console.log('Server started on port 3000');
});
- Ограничение скорости ведра токенов.
Алгоритм ведра токенов — еще один популярный метод ограничения скорости. Он включает в себя поддержку набора токенов, где каждый токен представляет запрос. Ведро имеет заранее определенную емкость, и токены добавляются с фиксированной скоростью. Когда поступает запрос, токен потребляется из корзины. Если ведро пусто, запрос отклоняется. Вот пример ограничения скорости сегмента токенов в Python:
import time
class TokenBucket:
def __init__(self, capacity, fill_rate):
self.capacity = capacity
self.fill_rate = fill_rate
self.tokens = capacity
self.last_fill_time = time.time()
def get_tokens(self):
now = time.time()
elapsed = now - self.last_fill_time
tokens_to_add = elapsed * self.fill_rate
self.tokens = min(self.tokens + tokens_to_add, self.capacity)
self.last_fill_time = now
return self.tokens
def consume_token(self):
tokens = self.get_tokens()
if tokens >= 1:
self.tokens -= 1
return True
return False
bucket = TokenBucket(capacity=100, fill_rate=10)
# Example usage
while True:
if bucket.consume_token():
# Process the request
print("Request processed")
else:
print("Rate limit exceeded")
time.sleep(0.1)
- Ограничение скорости скользящего окна.
При ограничении скорости скользящего окна вместо использования фиксированных временных окон для отслеживания запросов в течение определенного периода времени используется скользящее окно. Это обеспечивает большую гибкость в управлении пакетами запросов. Вот пример реализации на Ruby:
require 'time'
class SlidingWindowRateLimiter
def initialize(max_requests, window_duration)
@max_requests = max_requests
@window_duration = window_duration
@requests = []
end
def allow_request?
cleanup_requests
@requests.length < @max_requests
end
def add_request
cleanup_requests
@requests << Time.now
end
private
def cleanup_requests
@requests.delete_if { |request_time| request_time < Time.now - @window_duration }
end
end
# Example usage
limiter = SlidingWindowRateLimiter.new(max_requests: 100, window_duration: 60)
while true
if limiter.allow_request?
# Process the request
puts "Request processed"
limiter.add_request
else
puts "Rate limit exceeded"
end
sleep(0.1)
end