Skip to content

Latest commit

 

History

History
143 lines (96 loc) · 4.81 KB

limiters.rst

File metadata and controls

143 lines (96 loc) · 4.81 KB

Rush's Rate Limiting Algorithms

By default, rush includes the following algorithms:

  • Generic Cell Rate Limiting <rush.limiters.gcra.GenericCellRatelimiter>
  • Redis Lua Generic Cell rate Limiting <rush.limiters.redis_gcra.GenericCellRatelimiter>
  • Periodic <rush.limiters.periodic.PeriodicLimiter>

It also has a base class so you can create your own.

This class implements a very specific type of "leaky bucket" designed for Asynchronous Transfor Mode networks called Generic Cell Rate Algorithm. The algorithm itself can be challenging to understand, so let's first cover the benefits:

  • It doesn't require users to sit idle for a potentially long period of time while they wait for their period to be done.
  • It leaks the used amount of resources based off a clock and requires no extra threads, processes, or some other process to leak things.
  • It is fast, even implemented purely in Python.

This can be thought of as having a sliding window where users have some number of requests they can make. This means that even as time moves, your users can still make requests instead of waiting terribly long.

Example instantiation:

from rush.limiters import gcra
from rush.stores import dictionary

gcralimiter = gcra.GenericCellRatelimiter(
   store=dictionary.DictionaryStore()
)

This class implements a very specific type of "leaky bucket" designed for Asynchronous Transfor Mode networks called Generic Cell Rate Algorithm. The algorithm itself can be challenging to understand, so let's first cover the benefits:

  • It doesn't require users to sit idle for a potentially long period of time while they wait for their period to be done.
  • It leaks the used amount of resources based off a clock and requires no extra threads, processes, or some other process to leak things.
  • It is fast, even implemented purely in Python.

This can be thought of as having a sliding window where users have some number of requests they can make. This means that even as time moves, your users can still make requests instead of waiting terribly long.

This relies on Lua scripts that are loaded into Redis (and only compatible with Redis) and called from Python. The Lua scripts are borrowed from https://github.com/rwz/redis-gcra

Since this is implemented only for Redis this requires you to use ~rush.stores.redis.RedisStore.

Example instantiation:

from rush.limiters import redis_gcra
from rush.stores import redis

gcralimiter = redis_gcra.GenericCellRatelimiter(
   store=redis.RedisStore("redis://localhost:6379")
)

This class uses a naive way of allowing a certain number of requests for the specified period of time. If your quota has a period of 60 seconds and a limit (count and maximum burst) of 60, then effectively a user can make 60 requests every 60 seconds - or 1 request per second. For example, let's say a user makes a request at 12:31:50 until 12:32:50, they would only have 59 requests remaining. If by 12:32:10 the user has made 60 requests, then they still have to wait until 12:32:50 before they can make more.

Example instantiation:

from rush.limiters import periodic
from rush.stores import dictionary

periodiclimiter = periodic.PeriodicLimiter(
   store=dictionary.DictionaryStore()
)

Writing Your Own Algorithm

Rush specifies a very small set of methods that a Rate Limiter needs to implement in order to be usable in a throttle.

rush.limiters.base.BaseLimiter

Users can inherit from this class to implement their own Rate Limiting Algorithm. Users must define the rate_limit and reset methods. The signatures for these methods are:

def rate_limit(
    self, key: str, quantity: int, rate: quota.Quota
) -> result.RateLimitResult:
   pass

def reset(self, key: str, rate: quota.Quota) -> result.RateLimitResult:
   pass

The rate parameter will always be an instance of ~rush.quota.Quota.

store

This is the passed in instance of a Storage Backend <storage>. The instance must be a subclass of ~rush.stores.base.BaseStore.