GithubHelp home page GithubHelp logo

token-bucket's Introduction

Token bucket

Token buckets are a way to limit rate. You add (drip) tokens into a bucket of some size at some rate. If the bucket is full, no more tokens are added. Code can request a certain number of tokens as a prerequisite to permitting certain behavior.

The bigger the bucket, the more "burstiness" you can handle without inhibiting rate. The faster you add tokens, the higher the permissable rate.

Generally, token buckets come in two flavors:

  • Strict: A request for some number of tokens blocks until that many tokens can be consumed.
  • Non-Strict: (Relaxed) A request for some number of tokens consumes the minimum of the number of tokens available or the number requested, and does not block.

Note: There is some confusion in the literature around the name "token bucket", and the related term "leaky bucket", so take the terminology with a grain of salt.

Simple usage

The simplest usage is a bucket that adds tokens at a fixed rate, up to a given size:

val bucketRate: FiniteDuration = 100.millis
val bucketSize: Long = 10L
val bucket = BucketBuilder(bucketRate, bucketSize)

A bucket created in this way has the following properties:

  • A token will be added to the bucket every 100ms
  • The bucket will keep up to 10 tokens
  • Requests for tokens are threadsafe
  • Is "Strict".

So, assuming the above bucket has had a chance to fill completely:

bucket.requestTokens(10) // doesn't block
// but now the bucket is empty, so
bucket.requestTokens(10) // blocks for 100ms * 10 = 1 sec

There is also a threadsafe asynchronous interface to these simple buckets:

val tokenFuture: Future[Long] = bucket.tokenF(10)
// since this is a Strict bucket, the future value will always be the number of tokens requested.
tokenFuture.map(_ => sendHttpRequest()) 

//or if you prefer
bucket.rateLimitedAsync(10) {
  sendHttpRequest()
}

Design

The BucketBuilder interface is just assembling a bucket with certain common characteristics, and adding some convienence methods. Custom buckets can be crafted to taste by mixing certain traits.

Some examples of bucket classes you could create:

// Non-threadsafe, Non-Strict bucket with a certain number of starting tokens. More tokens are never added, making this not very useful.
class OneShotBucket(override val initialCapacity: Int) extends TokenBucketBase with InitialCapacity

// Threadsafe version of the same.
class ThreadsafeOneShotBucket(override val initialCapacity: Int) extends TokenBucketBase with InitialCapacity with Threadsafe 

// Non-Threadsafe, Non-Strict bucket with no initial tokens and no maximum capacity(!) that adds a token every 100ms
class NonStrictBucket extends TokenBucketBase with Refillable {
  override val source: TokenSource = TimeTokenSource(100.millis)
}

The BucketBuilder can also be used to wrap convenience functions around buckets that match certain required behavior:

val asyncBucket = BucketBuilder(<any Strict and Threadsafe bucket>)
asyncBucket.rateLimitedAsync(1) {
  ...
}

Concurrency

Although buckets can be thread-safe, the default thread safety implementation is just a lock, so watch your threads.

The async interfaces use an ExecutionContext to find a thread to block on, and the blocking call is marked appropriately.

References

I wanted a leaky bucket implmementation that made rate-limited asynchronous operations easy in Scala. There were a few other libraries that came close that are worth mentioning.

token-bucket's People

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.