aimdcloser

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2019 License: Apache-2.0 Imports: 3 Imported by: 0

README

aimdcloser

Build Status GoDoc Coverage Status

aimdcloser is a closer implementation for github.com/cep21/circuit. It is a closer that increases how many requests it allows in an opened circuit according to Additive increase/multiplicative decrease algorithm. The circuit closes when for a configured duration:

  • No requests have failed
  • No requests have been not allowed (additive increase is high enough for the rate)

Usage

Have your manager use a ratecloser.CloserFactory and your circuits will be created of this type.

    func ExampleCloserFactory() {
        // Tell your circuit manager to use the rate limited closer
        m := circuit.Manager{
            DefaultCircuitProperties: []circuit.CommandPropertiesConstructor{
                func(_ string) circuit.Config {
                    return circuit.Config{
                        General: circuit.GeneralConfig{
                            OpenToClosedFactory:CloserFactory(CloserConfig{
                                CloseOnHappyDuration: time.Second * 10,
                            }),
                        },
                    }
                },
            },
        }
        // Make circuit from manager
        c := m.MustCreateCircuit("example_circuit")
        // The closer should be a closer of this type
        _ = c.OpenToClose.(*Closer)
        // Output:
    }

Benchmarks

Run on my mac.

    < go test -bench .
    goos: darwin
    goarch: amd64
    pkg: github.com/cep21/aimdcloser/ratecloser
    BenchmarkCloser_Allow_10-16                	10000000	       155 ns/op	       0 B/op	       0 allocs/op
    BenchmarkCloser_AllowSuccess_10-16         	 5000000	       392 ns/op	       0 B/op	       0 allocs/op
    BenchmarkCloser_AllowSuccessClose_10-16    	 3000000	       480 ns/op	       0 B/op	       0 allocs/op
    BenchmarkCloser_AllowFailureClose_10-16    	 3000000	       513 ns/op	       0 B/op	       0 allocs/op
    PASS
    ok  	github.com/cep21/aimdcloser/ratecloser	8.108s

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AIMDConstructor

func AIMDConstructor(additiveIncrease float64, multiplicativeDecrease float64, initialRate float64, burst int) func() RateLimiter

AIMDConstructor constructs rate limiters according to the given parameters. See documentation for AIMD for what each parameter means.

Types

type AIMD

type AIMD struct {
	// How many requests / sec are allowed in addition when a success happens.  A default o zero
	// does not increase the rate.
	AdditiveIncrease float64
	// What % (0.0, 1.0) of requests to allow fewer of on a failure.  A default of zero
	// does not decrease the rate.
	MultiplicativeDecrease float64
	// The initial rate of requests / sec to set an AIMD at when reset.
	// Default of zero means infinite bursts per second.  However, with a burst of zero it is zero
	InitialRate float64
	// Allow Burst limits in the period
	// Default 0 turns off AIMD entirely.
	Burst int
	// contains filtered or unexported fields
}

AIMD is https://en.wikipedia.org/wiki/Additive_increase/multiplicative_decrease It is *NOT* thread safe

func (*AIMD) AttemptReserve

func (a *AIMD) AttemptReserve(now time.Time) bool

AttemptReserve tries to reserve a request inside the current time window. Returns if the rate limiter allows you to reserve a request.

Example
x := AIMD{
	// Add .1 req / sec for each successful request
	AdditiveIncrease: .1,
	// Decrease the rate by .5 for each failure
	MultiplicativeDecrease: .5,
	// Allows one request per millisecond
	InitialRate: 1 / time.Millisecond.Seconds(),
	// Burst to 10 in a time period
	Burst: 10,
}
if x.AttemptReserve(time.Now()) {
	fmt.Println("We make a request")
} else {
	fmt.Println("We skip making a request")
}
Output:

We make a request

func (*AIMD) OnFailure

func (a *AIMD) OnFailure(now time.Time)

OnFailure changes the limiter to decrease the current limit by MultiplicativeDecrease

Example
x := AIMD{
	// Add .1 req / sec for each successful request
	AdditiveIncrease: .1,
	// Decrease the rate by .5 for each failure
	MultiplicativeDecrease: .5,
	// Allows one request per millisecond
	InitialRate: 1 / time.Millisecond.Seconds(),
	// Burst to 10 in a time period
	Burst: 10,
}
if x.AttemptReserve(time.Now()) {
	fmt.Println("Request failed")
	x.OnFailure(time.Now())
}
Output:

Request failed

func (*AIMD) OnSuccess

func (a *AIMD) OnSuccess(now time.Time)

OnSuccess increases the reserved limit for this period.

Example
x := AIMD{
	// Add .1 req / sec for each successful request
	AdditiveIncrease: .1,
	// Decrease the rate by .5 for each failure
	MultiplicativeDecrease: .5,
	// Allows one request per millisecond
	InitialRate: 1 / time.Millisecond.Seconds(),
	// Burst to 10 in a time period
	Burst: 10,
}
if x.AttemptReserve(time.Now()) {
	fmt.Println("Request worked")
	x.OnSuccess(time.Now())
}
Output:

Request worked

func (*AIMD) Rate

func (a *AIMD) Rate() float64

Rate returns the current rate.

func (*AIMD) Reset

func (a *AIMD) Reset(now time.Time)

Reset the RateLimiter back to the initial rate and burst

type RateLimiter

type RateLimiter interface {
	// OnFailure is triggered each time we should lower our request rate.
	OnFailure(now time.Time)
	// OnSuccess is triggered each time we should increase our request rate.
	OnSuccess(now time.Time)
	// AttemptReserve is called when the application wants to ask if it should allow a request.
	AttemptReserve(now time.Time) bool
	// Reset the internal configuration of the rate limiter back to defaults.
	Reset(now time.Time)
}

RateLimiter is any object that can dynamically alter its reservation rate to allow more or less requests over time.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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