-
Notifications
You must be signed in to change notification settings - Fork 26
/
rate-limiting.go
68 lines (57 loc) · 2.2 KB
/
rate-limiting.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main
import (
"fmt"
"time"
)
// Rate limiting is an important mechanism for controlling resource utilization
// and maintaining quality of service.
// Go elegantly supports rate limiting with goroutines, channels, and tickers.
// RateLimiting illustrate controlling resource utilization and maintaining quality of service in go.
func RateLimiting() {
// First we’ll look at basic rate limiting.
// Suppose we want to limit our handling of incoming requests.
// We’ll serve these requests off a channel of the same name.
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
// This limiter channel will receive a value every 200 milliseconds.
// This is the regulator in our rate limiting scheme.
limiter := time.Tick(200 * time.Millisecond)
// By blocking on a receive from the limiter channel before serving each request,
// we limit ourselves to 1 request every 200 milliseconds.
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
}
// We may want to allow short bursts of requests in our rate limiting
// scheme while preserving the overall rate limit.
//We can accomplish this by buffering our limiter channel.
//This burstyLimiter channel will allow bursts of up to 3 events.
burstyLimiter := make(chan time.Time, 3)
// Fill up the channel to represent allowed bursting.
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
// Every 200 milliseconds we’ll try to add a new value to burstyLimiter, up to its limit of 3.
go func() {
for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t
}
}()
// Now simulate 5 more incoming requests.
// The first 3 of these will benefit from the burst capability of burstyLimiter.
burstyRequests := make(chan int, 5)
for i := 1; i <= 5; i++ {
burstyRequests <- i
}
close(burstyRequests)
for req := range burstyRequests {
<-burstyLimiter
fmt.Println("request", req, time.Now())
}
// Running our program we see the first batch of requests handled once every ~200 milliseconds as desired.
// For the second batch of requests we serve the first 3 immediately
// because of the burstable rate limiting, then serve the remaining 2 with ~200ms delays each.
}