zznicole / shopping-list

Ourshoppinglist is a Mobile-first Web application project. It was created by a team of two developers, using modern Javascript, ES6, React.js,Node.js DBOO database, Material UI, Arios......
0 stars 0 forks source link

Rate limiter #55

Open kft-a opened 3 years ago

kft-a commented 3 years ago

Rate limiters using a sliding window should be implemented:

In addtion, for statistics, keep track of number of requests for last (fixed window):

Add stats to the admin stats

Sliding window

Time is considered in fixed time periods. A counter is keeping track of the number of allowed requests within the time period (i.e. if above the limit do not count). If a new time period has been entered, the counter is zerod. If the number of request is above the limit, the request is dropped and otherwise allowed to be processed. The sliding part comes from that we also keep the number of requests of the last window and add a proportion of that to the current count when comparing to the limit. The proportion is the proportion of the current time window has passed. I.e. if we are 30% in to the current window, we add 70% of the last window's count when comparing to the limit.

kft-a commented 3 years ago

Not real code:

class RateLimiter {
  limit = 100; // number of requests allowed in window (set in constructor)
  windowSize = 60; // Window size in seconds (set in constructor)
  currentWindow = 0; // date time in seconds, actual clock for current window start
  lastWindowCounter = 0;
  currentCounter = 0;
  declinedRequests = 0;

  // Returns true if allow request, false if not
  function allow() {
    let windowStart = windowSize * int(now() / windowSize);
    let windowProportion = float((now() - windowStart) / windowSize);
    let lastWindowProportion = 1. - windowProportion;
    if (windowStart != currentWindow) {
      // start new window
      currentWindow = windowStart;
      // move counter to last window
      lastWindowCounter = currentCounter;
      currentCounter = 0;
      declinedRequests = 0;
    } 

    slidingCounter = currentCounter + lastWindowProportion * lastWindowCounter;
    if (slidingCounter > limit) {
      declinedRequests = declinedRequests + 1;
      return false;
    }
    currentCounter = currentCounter + 1;

    return true;
  }

};