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, если что-нибудь сломается.