Common rate-limiter implementations

Overview

An example Rate Limiter library used to control the rate that events occur, but these can also be used as thresholds that should replenish over time, such as error rates in circuit breakers.

How to use

go get -u github.com/wojnosystems/go-rate-limit

Examples

Regular Token Bucket


import (
	"github.com/wojnosystems/go-rate-limit/rateLimit"
	"log"
	"time"
)

const (
	actionCost = 2
)

func main() {
	limiter := rateLimit.NewTokenBucket(rateLimit.TokenBucketOpts{
		Capacity:             10,
		TokensAddedPerSecond: 10,
		InitialTokens:        5,
	})

	for {
		if !limiter.Allowed(actionCost) {
			break
		}
		log.Println("allowed!")
		time.Sleep(100 * time.Millisecond)
	}
	log.Println("done, finally not allowed")
}

In this example above, the rate limiter will fill at a rate of 10 tokens per second, up to a maximum of 10 tokens, but has a reserve to 5 tokens to start. When Allowed is called and sufficient tokens are available, it will print "allowed!". However, because our actionCost is 2, each call to Allowed will consume 2 tokens instead of just 1. If you specify 0 as the cost, it will consume no tokens and always allow.

Because we're consuming 2 tokens every 100ms, but we replenish 1 token every 100ms, we consume the initial tokens and 2 additionally generated tokens before outpacing the replenish rate. The application prints:

2021/11/28 23:11:34 allowed!
2021/11/28 23:11:34 allowed!
2021/11/28 23:11:34 allowed!
2021/11/28 23:11:34 allowed!
2021/11/28 23:11:34 done, finally not allowed

Bursting Token Bucket

This is just like the regular TokenBucket, but it can optionally burst over the limit and refill more slowly. This bucket also supports non-1 tokenCosts.

package main

import (
	"github.com/wojnosystems/go-rate-limit/rateLimit"
	"log"
	"time"
)

const (
	actionCost = 2
)

func main() {
	limiter := rateLimit.NewBurstingTokenBucket(
		rateLimit.BurstingTokenBucketOpts{
			Bucket: rateLimit.NewTokenBucket(rateLimit.TokenBucketOpts{
				Capacity:             10,
				TokensAddedPerSecond: 10,
				InitialTokens:        5,
			}),
			Burst:  rateLimit.NewTokenBucket(rateLimit.TokenBucketOpts{
				Capacity:             5,
				TokensAddedPerSecond: 1,
				InitialTokens:        1,
			}),
		})

	for {
		if !limiter.Allowed(actionCost) {
			break
		}
		log.Println("allowed!")
		time.Sleep(100 * time.Millisecond)
	}
	log.Println("done, finally not allowed")
}

It will output:

2021/11/28 23:53:18 allowed!
2021/11/28 23:53:18 allowed!
2021/11/28 23:53:18 allowed!
2021/11/28 23:53:18 allowed!
2021/11/28 23:53:18 allowed!
2021/11/28 23:53:19 done, finally not allowed

You can see that, compared to the regular TokenBucket example, we were able to burst out an additional "allowed!" thanks to our bursting bucket.

Usually, your main bucket fills a larger capacity quickly and your burst bucket fills a smaller capacity more slowly. That way, over time, you can burst, but it's smoothed out due to the slower re-generation rates.

For example, if your API allows 20 requests per second, with a burst of an additional 5 every 30 seconds, you could set up the BurstingTokenBucket:


import (
	"github.com/wojnosystems/go-rate-limit/rateLimit"
)

func main() {
	limiter := rateLimit.NewBurstingTokenBucket(
		rateLimit.BurstingTokenBucketOpts{
			Bucket: rateLimit.NewTokenBucket(rateLimit.TokenBucketOpts{
				Capacity:             20,
				TokensAddedPerSecond: 20,
			}),
			Burst:  rateLimit.NewTokenBucket(rateLimit.TokenBucketOpts{
				Capacity:             5,
				TokensAddedPerSecond: 5/30,
			}),
		})
		
    // ...
}

This means that every 6 seconds, a new bursting token will be available, while 120 new regular tokens will be available to use (with a maximum of 20 at any given second).

Owner
Chris Wojno
GoLang, Ruby on Rails, Java, C++ developer with a long history of web and video products, most of which aren't public, sadly. I love learning something new!
Chris Wojno
Similar Resources

Golang implementation of Sliding Window Algorithm for distributed rate limiting.

Golang implementation of Sliding Window Algorithm for distributed rate limiting.

slidingwindow Golang implementation of Sliding Window Algorithm for distributed rate limiting. Installation $ go get -u github.com/RussellLuo/slidingw

Dec 27, 2022

HTTP rate limiting module for Caddy 2

This module implements both internal and distributed HTTP rate limiting. Requests can be rejected after a specified rate limit is hit.

Jan 3, 2023

Light weight http rate limiting proxy

Introduction Light weight http rate limiting proxy. The proxy will perform rate limiting based on the rules defined in the configuration file. If no r

Dec 23, 2022

A little ping pong service that implements rate limiting with golang

Fred the Guardian Introduction Writing a little ping pong service that implements rate limiting with the programming language golang. Requirements Web

Jan 2, 2022

Gcra - Package gcra implements the generic cell rate algorithm

gcra Package gcra implements the generic cell rate algorithm (GCRA). Example opt

Jan 23, 2022

A Caddy v2 extension to apply rate-limiting for HTTP requests

ratelimit A Caddy v2 extension to apply rate-limiting for HTTP requests. Installation $ xcaddy build --with github.com/owlwang/caddy-ratelimit Caddyfi

Jan 28, 2022

Dhrate - Quickly check Dockerhub rate (limit) as an unauthenticated user

Dhrate - Quickly check Dockerhub rate (limit) as an unauthenticated user

Dockerhub Rate A small Go program that returns the Dockerhub rate of an unauthen

Feb 7, 2022

Ratelimit - This package provides a Golang implementation of the leaky-bucket rate limit algorithm

Go rate limiter This package provides a Golang implementation of the leaky-bucke

Jul 26, 2022

🧪 Run common networking tests against your site.

🧪 Run common networking tests against your site.

dstp dstp, run common networking tests against your site. Usage Usage: dstp [OPTIONS] [ARGS]

Jan 3, 2023
Redis-rate-limiter - An abstraction over redist rate/v9 package

RATE_LIMIT_POC Notes This POC is based on github.com/go-redis/redis_rate/v9 pack

Feb 14, 2022
A rate limiter for the gin framework

GinRateLimit GinRateLimit is a rate limiter for the gin framework. By default, it can only store rate limit info in memory. If you want to store it so

Dec 22, 2021
A rate limiter for Golang, with ETCD data bindings

Go Rate limiter This package allows us to have a distributed rate limiter, using Redis as a central counter. The limits that are set are only "soft" l

Dec 9, 2021
Go rate limiter used to ensure a minimum duration between executions.

Ratelimiter Rate limiter used to ensure a minimum duration between executions. Additionally supports the optional limit of max queue size. This can be

Jul 14, 2022
Pacemaker - Rate limit library. Currently implemented rate limits are

PaceMaker Rate limit library. Currently implemented rate limits are Fixed window

Nov 5, 2022
Turbine-common - This package contains the common interfaces for Turbine that are shared with other software

turbine-common This package contains the common interfaces for Turbine that are

Feb 12, 2022
Simple-request-limiter - Example of limiting API requests using standard Go library

Route: http://localhost:8080/urls example of body in POST request that was used:

Feb 2, 2022
Apollo Federation Gateway v1 implementations by Go

fedeway Apollo Federation Gateway v1 implementations by Go. ⚠️ This product is under development. don't use in production. ⚠️ TODO implements validati

Jan 6, 2023
Telemetry interfaces for logs and metrics allowing complete decoupling of instrumentation implementations.

Telemetry This package provides a set of Telemetry interfaces allowing you to completely decouple your libraries and packages from Logging and Metrics

Aug 9, 2022