Coder Social home page Coder Social logo

rate-limit's Introduction

Overview

Contains the primitives and utilities used to rate-limit / throttle Java applications, and a CircuitBreaker implementation.

Summary

Inspired by reading Cal Henderson's "Building Scalable Web Sites" which talks briefly about this, and having been on the receiving end of a kicking from search engines, I wanted to have a simple way of determining whether to bother processing requests and stop consuming server resources in a graceful way, rather than grinding to a halt.

Background - types of throttling

Next Service Slot

Each time a request comes in, we log the time. If it hasn't been a certain duration since the last request, then abort with a rate-limiting error.

key = create_key(request)

entry = gate.get_entry(key)

if (entry)
    response.set_status(SERVICE_UNAVAILABLE)
    return
end

entry = create_entry(expires => '5s')

gate.put_entry(key, entry)

...

Fixed Bucket

We define a duration and an acceptable number of requests to be serviced in that time. Each time a request comes in, we look up the number of calls made in the current period. If it is at or above the limit, then abort with a rate-limiting error, otherwise increment the counter and service the request.

key = create_key(request)

entry = gate.get_entry(key)

if (entry.count >= ALLOWED_PER_PERIOD)
    response.set_status(SERVICE_UNAVAILABLE)
    return
end

entry.count.increment()

...

From this description, it can be seen that Next Service Slot is essentially Fixed Bucket with a max size of 1 and an appropriate service period.

Leaky Bucket

Similar to a Fixed Bucket, except that rather than aborting, we block until the end of the current time period upon which the bucket counter is decremented / completely emptied and then we service the request.

Hardest to implement, has the disadvantage that it will tie up a request-handling thread (which may cause upstream services to timeout / retry) but may be a good solution in other contexts.

key = create_key(request)

entry = gate.get_entry(key)

if (entry.count >= ALLOWED_PER_PERIOD)
    entry.wait()
end

entry.count.increment()

...

CircuitBreaker

There is some overlap in the intention of this library with the Circuit Breaker approach described by Michael Nygard in his excellent book "Release It!"; I've done some work to add support for that as well. We've been running it in production for a year and it works well for our purposes.

Please see the tests for details as to how to use it.

rate-limit's People

Contributors

jabley avatar

Stargazers

weijh avatar  avatar  avatar Gary_Liu avatar  avatar Mat avatar  avatar 51pwn avatar Yaohua Zhao avatar YangMieMie avatar Werner Keil avatar Helder Guilherme Farias avatar Shridhar Navanageri avatar caibinbing avatar Alexander Fefelov avatar wifibaby4u avatar  avatar  avatar Doggie Yang avatar Agent Digital avatar David Luu avatar Sarang avatar CosmoW avatar  avatar BlancosWay avatar  avatar Angus H. avatar dikeke avatar  avatar  avatar Erik Beeson avatar  avatar debugerman avatar Sathish Kandasamy avatar André Abreu avatar  avatar Jiny Thattil avatar Chakra avatar Sharmarke Aden avatar Wonhee Jung avatar Randeep avatar G.Grandes avatar Mark Lee avatar Mateusz "Serafin" Gajewski avatar Ankur Chauhan avatar Mark Hellkamp avatar Domenico Giffone avatar  avatar  avatar Nishant Chandra avatar Andrew NS Yeow avatar Rich Kroll avatar Olivier Bazoud avatar Aldrin Leal avatar Bradley Dwyer avatar Daniel Marchant avatar  avatar Nick Gerakines avatar

Watchers

David Drugeon-Hamon avatar James Cloos avatar happyguozf avatar Randeep avatar Chakra avatar  avatar

rate-limit's Issues

FixedBucket size shows up in memory profile

Seen a heap dump that contained a 25MB FixedBucket.

This was using a MemoryTokenStore and the HashMap ivar contained 524,288 members.

There is presumably some scope to reduce the footprint of that item?

Implement leaky bucket

Leaky Bucket is described, but not currently implemented. I haven't needed it yet, so if others do, then vote for it here.

missed calling lock()?

In method create(Key key, int timeToLiveInSecs) at class CoarseMemoryTokenStore, it seems that lock() call is missed.

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.