/
rate.go
97 lines (90 loc) · 1.75 KB
/
rate.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package xtools
import (
"sync"
"time"
"github.com/bluele/gcache"
)
type (
RateInter interface {
Rate() float64
Succ()
Fail()
}
AcRate struct {
lock *sync.RWMutex
succ gcache.Cache
fail gcache.Cache
keyfunc RateKeyFunc
}
RateKeyFunc func() interface{}
ActionFunc func() error
Breaker struct {
id string
status int // 0 熔断器关闭状态 1 熔断器打开 2 半熔断
circuitTime int // 熔断时间 s
CircuitRate float64 //熔断的成功率
recoverNum int //半熔断 成功N 次恢复
ctrl RateInter
}
)
func NewAcRate(sec int) *AcRate {
return &AcRate{
succ: gcache.New(sec * 2).Expiration(time.Duration(sec) * time.Second).LRU().Build(),
fail: gcache.New(sec * 2).Expiration(time.Duration(sec) * time.Second).LRU().Build(),
keyfunc: func() interface{} {
return time.Now().Unix()
},
lock: &sync.RWMutex{},
}
}
func (h *AcRate) SetKeyFunc(ac RateKeyFunc) {
if ac == nil {
return
}
h.keyfunc = ac
}
func (h *AcRate) Rate() float64 {
succdata := h.succ.GetALL(true)
faildata := h.fail.GetALL(true)
all, fail := int64(0), int64(0)
for _, v := range succdata {
val, isok := v.(int64)
if isok {
all = all + val
}
}
for _, v := range faildata {
val, isok := v.(int64)
if isok {
all = all + val
fail = fail + val
}
}
if all < 1 {
return 100
} else if fail == all {
return 0
}
return float64((all-fail)*100) / float64(all)
}
func (h *AcRate) Succ() {
h.incr(h.succ)
}
func (h *AcRate) Fail() {
h.incr(h.fail)
}
func (h *AcRate) incr(c gcache.Cache) {
dt := h.keyfunc()
h.lock.Lock()
defer h.lock.Unlock()
val, err := c.Get(dt)
if err != nil {
c.Set(dt, int64(1))
return
}
v, isok := val.(int64)
if !isok {
v = 0
}
c.Set(dt, v+1)
}