Simple backoff algorithm in Go (golang)
A simple exponential backoff counter in Go (Golang)
$ go get -v github.com/jpillora/backoff
Backoff is a
time.Durationcounter. It starts at
Min. After every call to
Duration()it is multiplied by
Factor. It is capped at
Max. It returns to
Minon every call to
Reset().
Jitteradds randomness (see below). Used in conjunction with the
timepackage.
b := &backoff.Backoff{ //These are the defaults Min: 100 * time.Millisecond, Max: 10 * time.Second, Factor: 2, Jitter: false, }fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration())
fmt.Printf("Reset!\n") b.Reset()
fmt.Printf("%s\n", b.Duration())
100ms 200ms 400ms Reset! 100ms
netpackage
b := &backoff.Backoff{ Max: 5 * time.Minute, }for { conn, err := net.Dial("tcp", "example.com:5309") if err != nil { d := b.Duration() fmt.Printf("%s, reconnecting in %s", err, d) time.Sleep(d) continue } //connected b.Reset() conn.Write([]byte("hello world!")) // ... Read ... Write ... etc conn.Close() //disconnected }
Jitter
Enabling
Jitteradds some randomization to the backoff durations. See Amazon's writeup of performance gains using jitter. Seeding is not necessary but doing so gives repeatable results.
import "math/rand"b := &backoff.Backoff{ Jitter: true, }
rand.Seed(42)
fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration())
fmt.Printf("Reset!\n") b.Reset()
fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration()) fmt.Printf("%s\n", b.Duration())
100ms 106.600049ms 281.228155ms Reset! 100ms 104.381845ms 214.957989ms
https://godoc.org/github.com/jpillora/backoff
Forked from some JavaScript written by @tj