Rate Limiting в TypeScript: полное руководство по библиотекам и реализации
Rate limiting (ограничение скорости запросов) — это механизм контроля трафика, который предотвращает перегрузку сервера, защищает от DDoS-атак и обеспечивает равномерное распределение ресурсов. В TypeScript, благодаря строгой типизации и поддержке асинхронности, реализация rate limiting становится особенно удобной. В этой статье мы разберем популярные библиотеки, стратегии и примеры кода для TypeScript.
Зачем нужен Rate Limiting?
- Защита API — ограничение числа запросов от одного клиента (по IP, токену или ID).
- Предотвращение злоупотреблений — блокировка ботов или скриптов, генерирующих чрезмерную нагрузку.
- Распределение ресурсов — честное использование бэкенда между пользователями.
- Соблюдение лимитов внешних сервисов — контроль запросов к сторонним API (например, OpenAI или GitHub).
Популярные библиотеки для Rate Limiting в TypeScript
1. express-rate-limit
Самая популярная библиотека для Express.js. Работает как middleware, поддерживает TypeScript из коробки. Позволяет задать лимит по времени и кастомные обработчики превышения.
Установка:
npm install express-rate-limit
npm install -D @types/express-rate-limit
Пример использования:
import express from 'express';
import rateLimit from 'express-rate-limit';
const app = express();
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: 100, // максимум 100 запросов за окно
message: 'Слишком много запросов, попробуйте позже.',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api', limiter); // Применяем к /api/*
app.get('/api/data', (req, res) => {
res.json({ message: 'Успешный ответ' });
});
app.listen(3000);
Особенности:
- Встроенная поддержка TypeScript (типы для
RequestиResponse). - Гибкая настройка: можно задать ключ (по IP, userId, токену).
- Хранение состояния в памяти (по умолчанию) или через Redis.
2. bottleneck
Библиотека для клиентского rate limiting — идеальна, когда нужно контролировать исходящие запросы (например, к внешнему API). Работает на основе очередей и задержек.
Установка:
npm install bottleneck
Пример с TypeScript:
import Bottleneck from 'bottleneck';
const limiter = new Bottleneck({
minTime: 200, // минимум 200 мс между запросами
maxConcurrent: 5, // максимум 5 одновременных запросов
reservoir: 100, // общий лимит на период
reservoirRefreshAmount: 100,
reservoirRefreshInterval: 60 * 1000, // каждые 60 секунд
});
async function fetchData(id: number): Promise<string> {
const response = await fetch(`https://api.example.com/data/${id}`);
return response.text();
}
// Оборачиваем функцию с лимитированием
const limitedFetch = limiter.wrap(fetchData);
// Использование
async function main() {
const results = await Promise.all([
limitedFetch(1),
limitedFetch(2),
limitedFetch(3),
]);
console.log(results);
}
Плюсы:
- Поддерживает типы для оборачиваемой функции.
- Гибкие стратегии:
minTime,maxConcurrent,reservoir. - Работает как в Node.js, так и в браузере.
3. p-limit
Легковесная библиотека для ограничения параллельных асинхронных операций. Полезна, когда нужно контролировать количество одновременно выполняемых промисов.
Установка:
npm install p-limit
Пример:
import pLimit from 'p-limit';
const limit = pLimit(3); // максимум 3 одновременных запроса
const inputs = [1, 2, 3, 4, 5, 6, 7, 8];
async function fetchItem(id: number): Promise<string> {
const response = await fetch(`/api/item/${id}`);
return response.text();
}
const promises = inputs.map((id) => limit(() => fetchItem(id)));
const results = await Promise.all(promises);
Особенность: отлично подходит для работы с массивами данных, когда нужно избежать перегрузки сети или базы данных.