Tl; dr Используйте Ratelimit.js для быстрого и удобного ограничения скорости Node.js,
Ограничение скорости - довольно распространенная практика среди веб-разработчиков, поскольку позволяет ограничить определенную активность в пределах набора параметров. Часто он используется для ограничения количества запросов, которые может сделать определенный пользователь, но у него есть и другие варианты использования, такие как регулирование события или ограничение количества запросов API, которые делает приложение. Что касается Node.js и Express, ограничение скорости ваших маршрутов с помощью промежуточного программного обеспечения кажется неплохим вариантом. Войдите в Ratelimit.js.
Обзор
Ratelimit.js реализует технику ограничения скорости скользящего окна, обсуждаемую в этом сообщении блога, а также этом сообщении блога. Вы определяете набор правил, определяемых интервалом и лимитом, а Ratelimit.js делает все остальное. Описанный выше вариант использования Node.js легко достигается с помощью включенного промежуточного программного обеспечения Express. Ratelimit.js использует Redis для постоянства, поэтому при условии, что вы используете одно и то же соединение Redis для всех экземпляров вашего приложения, вы бесплатно получаете распределенное ограничение скорости. Если вы уже используете Redis для хранения сеансов, у вас все готово.
Вот пример приложения Express, которое применяет ограничения скорости на всех своих конечных точках:
var express = require('express'); var RateLimit = require('ratelimit.js').RateLimit; var ExpressMiddleware = require('ratelimit.js').ExpressMiddleware; var redis = require('redis'); var app = express(); var rateLimiter = new RateLimit(redis.createClient(), [{interval: 1, limit: 10}]); var limitMiddleware = new ExpressMiddleware(rateLimiter); app.use(limitMiddleware.middleware(function(req, res, next) { res.status(429).json({message: 'rate limit exceeded'}); })); app.get('/', function(req, res, next) { // this request has not exceeded the configured rate limits res.status(200).json({message: 'under configured rate limits'}); }); app.listen(3000);
Промежуточное использование
Один немного сложный вариант использования - это применение разных ограничений скорости для пользователей в разных местах. Это легко сделать с помощью комбинации геолокации IP и Ratelimit.js. Что касается геолокации IP, я бы порекомендовал посмотреть базу данных Maxmind GeoLite2 и node-maxmind-db.
... var app = express(); var defRateLimiter = new RateLimit(redis.createClient(), [{interval: 1, limit: 10}], 'default_rate_limit'); var defMiddleware = new ExpressMiddleware(defRateLimiter); var ukRateLimiter = new RateLimit(redis.createClient(), [{interval: 1, limit: 20}], 'uk_rate_limit'); var ukMiddleware = new ExpressMiddleware(ukRateLimiter); var rateLimitResponder = function(req, res, next) { res.status(429).json({message: 'Rate limit exceeded.'}); }; var geoLimiters = { default: defMiddleware.middleware(rateLimitResponder), uk: ukMiddleware.middleware(rateLimitResponder); }; var limitFn = function(req, res, next) { var reqIsoCode = getIsoCode(req); var limiterMiddleware = geoLimiters[reqIsoCode] || geoLimiter.default; limiterMiddleware(req, res, next); }; app.get('/', limitFn, function(req, res, next) { // request is not rate limited ... }); ...
Ключевым моментом является то, что вы должны различать два ограничителя скорости с помощью настраиваемого префикса (см. Конструкторы RateLimit). То, как IP-адреса (или другой указанный вами идентификатор запроса) не будет конфликтовать. Если у вас есть возможность реализовать функцию getIsoCode, у вас есть ограничения скорости для разных языков примерно в 35 строках кода. Неплохо.
Да, и полное раскрытие - Я помогал это писать! Но вы можете поставить ошибку @dudley, если что-нибудь сломается.