A Golang blocking leaky-bucket rate limit implementation

Related tags

ratelimit
Overview

Go rate limiter GoDoc Coverage Status test

This package provides a Golang implementation of the leaky-bucket rate limit algorithm. This implementation refills the bucket based on the time elapsed between requests instead of requiring an interval clock to fill the bucket discretely.

Create a rate limiter with a maximum number of operations to perform per second. Call Take() before each operation. Take will sleep until you can continue.

import (
	"fmt"
	"time"

	"go.uber.org/ratelimit"
)

func main() {
    rl := ratelimit.New(100) // per second

    prev := time.Now()
    for i := 0; i < 10; i++ {
        now := rl.Take()
        fmt.Println(i, now.Sub(prev))
        prev = now
    }

    // Output:
    // 0 0
    // 1 10ms
    // 2 10ms
    // 3 10ms
    // 4 10ms
    // 5 10ms
    // 6 10ms
    // 7 10ms
    // 8 10ms
    // 9 10ms
}
Issues
  • Update the Limiter interface to accept a context.Context object

    Update the Limiter interface to accept a context.Context object

    This also removes the Clock abstraction, since there doesn't seem to be a way to create timers using the mock clock effectively, and it isn't used in yab at all. I can add it back in and try to munge it to work if it has value.

    opened by achals 9
  • Feature Request: Allow updating the limit

    Feature Request: Allow updating the limit

    Goal: To use this library with an adaptive rate limiter algorithm like Vegas or AIMD

    Problem: Right now the library exposes no way to update the rates dynamically.

    There are two ways to solve for this

    1. Create a new rate limiter every time I want to update limits
    2. Dynamically update the rate limit on the object

    Would like feedback on which is the preferred approach. Or if there is any other way.

    opened by prathik 8
  • Add Per option

    Add Per option

    Commits are individually reviewable. The first changes address nits I missed in review.

    The final change addresses #17 by adding an option called Per that reads ratelimit.New(1, Per(time.Second)) for a 1Hz rate limiter.

    opened by kriskowal 7
  • add unsafe limiter

    add unsafe limiter

    usage scenario: single thread(goroutine)

    opened by mmaxiaolei 7
  • Parity with yab ratelimit

    Parity with yab ratelimit

    I was trawling through the yab ratelimiting code, and noticed that the interface exposed there is different (and IMO nicer) than the interface in this package.

    Is this package intended to be kept updated? If so, would it be possible to update the implementation to bring it up the parity? I'd be more than happy to contribute a PR if it would help. It would be great to be able to use rate limiting logic independently of yab.

    opened by achals 6
  • Atomic based limiter

    Atomic based limiter

    Hi, I've made your limiter implementation atomic based. It is a little bit harder but in generally faster and has no goroutine scalability issues that any mutex based implementation have. Checkout this relation between RateLimiter latency and count of goroutines: limiter_scalability Original implementation moved to mutexbased.go file, so you can run benchmarks and play with other tests. But I'd suggest to leave only one implementation after all.

    [Side note] This wired latency spike in mutex based implementation is a direct illustration of mutex falling into starvation mode.

    Full benchmarking results here

    opened by storozhukBM 6
  • Prefactor types into a separarate types package

    Prefactor types into a separarate types package

    This came up in #37 where we ended up in a dependency loop.

    • main package was importing a specific rate limiter type
    • both rate limiters needed to import Clock types from main package

    By moving it to a separate package we avoid that loop.

    If we decide to go ahead with #37, this will also be necessary to have a "common config type" that can be re-used between all N alternative limiters.

    opened by rabbbit 4
  • Get rid of nap with gopeek

    Get rid of nap with gopeek

    The below is quoted from https://github.com/uber-go/ratelimit/pull/1#discussion-diff-78767601 .

    Alternatively, if this is purely for testing, we could have a "sleep till there's no runnable goroutines" function. There's no easy way to do it, but we'd get a list of all goroutines, and make sure that they're all blocked on something.

    As I felt there are not negligible such needs especially for testing I've developed https://github.com/cat2neat/gopeek to realise the above requirements in a generalized way.

    This PR would

    • get rid of nap with gopeek
    • get the test time speed up around 3times.
    • get the test more stable in a resource constrained one like travis-ci as time.Sleep tend to be unstable
    opened by cat2neat 4
  • Get rid of internal/clock - Consolidate AfterFunc and Sleep in tests

    Get rid of internal/clock - Consolidate AfterFunc and Sleep in tests

    Resolves #3

    Was looking at the open issues and #3 seemed to make sense - it was also something that I saw in #37 so I thought I'd take a stab.

    The reasoning is that less code + smaller interface is a good thing.

    During the diff it turned out that:

    • our internal/clock has no tests
    • our internal/clock has at least two bugs:
      • one that I'm fixing here, related to not executing two timers if they're scheduled at the "now" boundry
      • one regarding adding time but not having a timer set for that specific time (not a problem for us, so not touching it)

    By dropping afterFunc into Sleep we're able to deprecate the internal fork altogether - there is a missing nap in andres-erbsen/clock.AfterFunc that meant we needed our own fork. Now it's not needed.

    opened by rabbbit 4
  • Need to get the last sleepFor in the loop.

    Need to get the last sleepFor in the loop.

    Need to get the last sleepFor in the loop, or slack will have no effect.

    opened by QuantumEnergyE 4
  • If add some check in New function?

    If add some check in New function?

    when I use ticker := ratelimit.New(0) the code will throw exception, but when I use negative I works ok but loss my mind. ticker := ratelimit.New(-1) Pre-Request wait 10s. if need add some check in when new a litter?

    opened by GuoGuiRong 0
  • Evaluate atomic and mutex based Take implementations.

    Evaluate atomic and mutex based Take implementations.

    #15 brought in a new implementation of Take to avoid starving out the older mutex implementation (a major performance win). Before we cut a new release, let's dive a little deeper on the new implementation's behaviors and aim for a single implementation.

    opened by twilly 1
  • Investigate table runner for the impact of slack

    Investigate table runner for the impact of slack

    Currently we are unable to observe the difference between ratelimit with and without slack. Investigate a test that makes the difference observable and verifiable.

    opened by kriskowal 1
Owner
Uber Go
Uber's open source software for Go development
Uber Go
A timed rate limiter for Go

go-rate go-rate is a rate limiter designed for a range of use cases, including server side spam protection and preventing saturation of APIs you consu

Michael Alexander 338 Jul 15, 2021
A Golang blocking leaky-bucket rate limit implementation

Go rate limiter This package provides a Golang implementation of the leaky-bucket rate limit algorithm. This implementation refills the bucket based o

Uber Go 2.4k Jul 22, 2021
Simple middleware to rate-limit HTTP requests.

Tollbooth This is a generic middleware to rate-limit HTTP requests. NOTE 1: This library is considered finished. NOTE 2: Major version changes are bac

Didip Kerabat 2k Jul 27, 2021
Go package for rate limiter collection

rlc A rate limiter collection for Go. Pick up one of the rate limiters to throttle requests and control quota. RLC Slider TokenBucket RLC RLC is a rat

Alex Xu 15 Jul 6, 2021
Simple, thread-safe Go rate-limiter

RateLimit Simple, thread-safe Go rate-limiter. Inspired by Antti Huima's algorithm on http://stackoverflow.com/a/668327 Example package main import (

Black Square Media 66 May 3, 2021
Sentinel Go version (Reliability & Resilience)

Sentinel: The Sentinel of Your Microservices Introduction As distributed systems become increasingly popular, the reliability between services is beco

Alibaba 1.6k Jul 20, 2021
An efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern.

Circuit Circuit is an efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern. Learn more about the problems Hyst

Jack Lindamood 582 Jul 21, 2021
A tiny http middleware for Golang with added handlers for common needs.

rye A simple library to support http services. Currently, rye provides a middleware handler which can be used to chain http handlers together while pr

InVision 97 Jun 6, 2021
An experimental GraphQL implementation with Go.

Description An experimental GraphQL implementation with Go. This repo focuses on improve GraphQL Parse and Resolve speed t

karminski-牙医 57 Jul 9, 2021
Minimalist net/http middleware for golang

interpose Interpose is a minimalist net/http middleware framework for golang. It uses http.Handler as its core unit of functionality, minimizing compl

James Pirruccello 290 Jun 21, 2021
Composable chains of nested http.Handler instances.

chain go get github.com/codemodus/chain Package chain aids the composition of nested http.Handler instances. Nesting functions is a simple concept. I

Code Modus 63 Feb 11, 2021
Idiomatic HTTP Middleware for Golang

Negroni Notice: This is the library formerly known as github.com/codegangsta/negroni -- Github will automatically redirect requests to this repository

null 7k Jul 23, 2021
Go package for easily rendering JSON, XML, binary data, and HTML templates responses.

Render Render is a package that provides functionality for easily rendering JSON, XML, text, binary data, and HTML templates. This package is based on

Cory Jacobsen 1.5k Jul 27, 2021
Add interceptors to GO http.Client

mediary Add interceptors to http.Client and you will be able to Dump request and/or response to a Log Alter your requests before they are sent or resp

Here Mobility SDK 73 Jul 15, 2021