-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlimiter.go
83 lines (75 loc) · 1.62 KB
/
limiter.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package throtto
import (
"net/http"
"sync"
)
var lmt *limiter
var once sync.Once
//New create request limitter instance
func New(cfg *Config) RequestLimitter {
once.Do(func() {
if cfg == nil {
cfg = defConf()
}
lmt = &limiter{
cctrl: &cctrl{
flux: cfg.Flux,
sincr: cfg.MaxIncementRate,
fdcr: cfg.MaxDecrementRate,
},
lcap: &lcap{
thres: float64(2 * cfg.CapConfidence),
window: float64(cfg.CapConfidence),
},
lmem: &lmem{
wdrop: []float64{float64(cfg.CapConfidence * 2)},
},
lstate: new(lstate),
ltask: <ask{
tasks: make([]string, 0),
},
lweight: &lweight{
sw: cfg.Flux,
fw: 1.0 - cfg.Flux,
},
lcount: new(lcount),
rejectFunc: cfg.RejectFunc,
finish: make(chan bool, 1),
debug: cfg.Debug,
}
})
return lmt
}
func defConf() *Config {
return &Config{
Flux: DefFlux,
MaxIncementRate: DefMaxIncr,
MaxDecrementRate: DefMaxDecr,
CapConfidence: DefCapConf,
}
}
//RequestLimitter contract
//members:
// ProtectOverRequest bind the handler with request limitter
type RequestLimitter interface {
ProtectOverRequest(http.Handler) http.Handler
Stop()
}
//Config as request limitter configuration
type Config struct {
Flux float64
MaxIncementRate float64
MaxDecrementRate float64
CapConfidence int64
RejectFunc http.HandlerFunc
Debug bool
}
//ProtectOverRequest protect handler from exceeding request
func (l *limiter) ProtectOverRequest(next http.Handler) http.Handler {
go l.ptick()
go l.pschedule()
return limitHandler(l, next)
}
func (l *limiter) Stop() {
l.finish <- true
}