ratelimit

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2024 License: MIT Imports: 5 Imported by: 685

README

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
}

FAQ:

  • What's the major diff v.s. https://pkg.go.dev/golang.org/x/time/rate? (based on #77)

    This ratelimiter was meant to have a (1) simple API and (2) minimal overhead. For more complex use-cases x/time/rate is a great choice. See here for historical context, and here for benchmarks (from 2016).

  • Why does example_test.go fail when I run it locally on Windows? (based on #80)

    Windows has some known issues with timers precision. See golang/go#44343. We don't expect to work around it.

Documentation

Overview

Example (Default)
package main

import (
	"fmt"
	"time"

	"go.uber.org/ratelimit"
)

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

	rl.Take()                         // Initialize.
	time.Sleep(time.Millisecond * 45) // Let some time pass.

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

}
Output:

1 0s
2 0s
3 0s
4 4ms
5 10ms
6 10ms
7 10ms
8 10ms
9 10ms
Example (WithoutSlack)
package main

import (
	"fmt"
	"time"

	"go.uber.org/ratelimit"
)

func main() {
	rl := ratelimit.New(100, ratelimit.WithoutSlack) // per second, no slack.

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

}
Output:

1 10ms
2 10ms
3 10ms
4 10ms
5 10ms

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Clock

type Clock interface {
	Now() time.Time
	Sleep(time.Duration)
}

Clock is the minimum necessary interface to instantiate a rate limiter with a clock or mock clock, compatible with clocks created using github.com/andres-erbsen/clock.

type Limiter

type Limiter interface {
	// Take should block to make sure that the RPS is met.
	Take() time.Time
}

Limiter is used to rate-limit some process, possibly across goroutines. The process is expected to call Take() before every iteration, which may block to throttle the goroutine.

func New

func New(rate int, opts ...Option) Limiter

New returns a Limiter that will limit to the given RPS.

func NewUnlimited

func NewUnlimited() Limiter

NewUnlimited returns a RateLimiter that is not limited.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures a Limiter.

var WithoutSlack Option = slackOption(0)

WithoutSlack configures the limiter to be strict and not to accumulate previously "unspent" requests for future bursts of traffic.

func Per added in v0.2.0

func Per(per time.Duration) Option

Per allows configuring limits for different time windows.

The default window is one second, so New(100) produces a one hundred per second (100 Hz) rate limiter.

New(2, Per(60*time.Second)) creates a 2 per minute rate limiter.

func WithClock

func WithClock(clock Clock) Option

WithClock returns an option for ratelimit.New that provides an alternate Clock implementation, typically a mock Clock for testing.

func WithSlack added in v0.2.0

func WithSlack(slack int) Option

WithSlack configures custom slack. Slack allows the limiter to accumulate "unspent" requests for future bursts of traffic.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL