-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflowControl.go
59 lines (53 loc) · 1.23 KB
/
flowControl.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
package flowControl
import (
"sync"
"time"
)
//滑动窗口实现流量控制
type RollWindow struct {
buf []int64
totalQps int64
currentQps int64
index int
lastSecond int64
sync.Mutex
}
//生成一个流量控制对象
//gridCount:滑动窗口格子数量,一个格子就是1秒
//totalQps:滑动窗口总qps,如gridCount=10,totalQps=50,qps = totalQps / gridCount = 5
func NewRollWindow(gridCount int, totalQps int64) *RollWindow {
return &RollWindow{
buf: make([]int64, gridCount),
totalQps: totalQps,
currentQps: 0,
index: 0,
}
}
//无锁流量控制,不支持多协程调用
func (fc *RollWindow) Wait() {
curTime := time.Now().UnixNano()
curSecond := curTime / int64(time.Second)
var startValue int64
if curSecond > fc.lastSecond {
fc.lastSecond = curSecond
fc.index++
if fc.index >= len(fc.buf) {
fc.index = 0
}
startValue = fc.buf[fc.index]
fc.buf[fc.index] = 0
}
fc.buf[fc.index]++
fc.currentQps++
fc.currentQps -= startValue
if fc.currentQps > fc.totalQps {
//睡到下一秒
time.Sleep(time.Second - time.Duration(curTime)%time.Second)
}
}
//有锁流量控制,支持多协程调用
func (fc *RollWindow) WaitLock() {
fc.Lock()
fc.Wait()
fc.Unlock()
}