Skip to content

Commit eecd776

Browse files
authored
Polish data-source helper for rules and rename package of freq_params_traffic module (alibaba#157)
* package rename: freq_params_traffic -> hotspot * Also polish code of rule managers
1 parent b2837c0 commit eecd776

32 files changed

+814
-311
lines changed

api/slot_chain.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"github.com/alibaba/sentinel-golang/core/base"
55
"github.com/alibaba/sentinel-golang/core/circuitbreaker"
66
"github.com/alibaba/sentinel-golang/core/flow"
7-
"github.com/alibaba/sentinel-golang/core/freq_params_traffic"
7+
"github.com/alibaba/sentinel-golang/core/hotspot"
88
"github.com/alibaba/sentinel-golang/core/log"
99
"github.com/alibaba/sentinel-golang/core/stat"
1010
"github.com/alibaba/sentinel-golang/core/system"
@@ -31,10 +31,10 @@ func BuildDefaultSlotChain() *base.SlotChain {
3131
sc.AddRuleCheckSlotLast(&system.SystemAdaptiveSlot{})
3232
sc.AddRuleCheckSlotLast(&flow.FlowSlot{})
3333
sc.AddRuleCheckSlotLast(&circuitbreaker.CircuitBreakerSlot{})
34-
sc.AddRuleCheckSlotLast(&freq_params_traffic.FreqPramsTrafficSlot{})
34+
sc.AddRuleCheckSlotLast(&hotspot.FreqPramsTrafficSlot{})
3535
sc.AddStatSlotLast(&stat.StatisticSlot{})
3636
sc.AddStatSlotLast(&log.LogSlot{})
3737
sc.AddStatSlotLast(&circuitbreaker.MetricStatSlot{})
38-
sc.AddStatSlotLast(&freq_params_traffic.ConcurrencyStatSlot{})
38+
sc.AddStatSlotLast(&hotspot.ConcurrencyStatSlot{})
3939
return sc
4040
}

core/circuitbreaker/rule.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func (b *RuleBase) IsStatReusable(r Rule) bool {
8383

8484
func (b *RuleBase) String() string {
8585
// fallback string
86-
return fmt.Sprintf("RuleBase{id=%s,resource=%s, strategy=%+v, RetryTimeoutMs=%d, MinRequestAmount=%d}",
86+
return fmt.Sprintf("{id=%s,resource=%s, strategy=%+v, RetryTimeoutMs=%d, MinRequestAmount=%d}",
8787
b.Id, b.Resource, b.Strategy, b.RetryTimeoutMs, b.MinRequestAmount)
8888
}
8989

@@ -140,7 +140,7 @@ func (r *slowRtRule) IsApplicable() error {
140140
}
141141

142142
func (r *slowRtRule) String() string {
143-
return fmt.Sprintf("slowRtRule{RuleBase:%s, MaxAllowedRt=%d, MaxSlowRequestRatio=%f}", r.RuleBase.String(), r.MaxAllowedRt, r.MaxSlowRequestRatio)
143+
return fmt.Sprintf("{slowRtRule{RuleBase:%s, MaxAllowedRt=%d, MaxSlowRequestRatio=%f}", r.RuleBase.String(), r.MaxAllowedRt, r.MaxSlowRequestRatio)
144144
}
145145

146146
// Error ratio circuit breaker rule
@@ -164,7 +164,7 @@ func NewErrorRatioRule(resource string, intervalMs uint32, retryTimeoutMs uint32
164164
}
165165

166166
func (r *errorRatioRule) String() string {
167-
return fmt.Sprintf("errorRatioRule{RuleBase:%s, Threshold=%f}", r.RuleBase.String(), r.Threshold)
167+
return fmt.Sprintf("{errorRatioRule{RuleBase:%s, Threshold=%f}", r.RuleBase.String(), r.Threshold)
168168
}
169169

170170
func (r *errorRatioRule) IsEqualsTo(newRule Rule) bool {
@@ -207,7 +207,7 @@ func NewErrorCountRule(resource string, intervalMs uint32, retryTimeoutMs uint32
207207
}
208208

209209
func (r *errorCountRule) String() string {
210-
return fmt.Sprintf("errorCountRule{RuleBase:%s, Threshold=%d}", r.RuleBase.String(), r.Threshold)
210+
return fmt.Sprintf("{errorCountRule{RuleBase:%s, Threshold=%d}", r.RuleBase.String(), r.Threshold)
211211
}
212212

213213
func (r *errorCountRule) IsEqualsTo(newRule Rule) bool {

core/circuitbreaker/rule_manager.go

+56-42
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package circuitbreaker
22

33
import (
4-
"encoding/json"
54
"fmt"
5+
"strings"
66
"sync"
77

88
"github.com/alibaba/sentinel-golang/logging"
@@ -82,6 +82,12 @@ func GetResRules(resource string) []Rule {
8282
return ret
8383
}
8484

85+
// ClearRules clear all the previous rules
86+
func ClearRules() error {
87+
_, err := LoadRules(nil)
88+
return err
89+
}
90+
8591
// LoadRules replaces old rules with the given circuit breaking rules.
8692
//
8793
// return value:
@@ -106,6 +112,42 @@ func getResBreakers(resource string) []CircuitBreaker {
106112
return ret
107113
}
108114

115+
func calculateReuseIndexFor(r Rule, oldResCbs []CircuitBreaker) (equalIdx, reuseStatIdx int) {
116+
// the index of equivalent rule in old circuit breaker slice
117+
equalIdx = -1
118+
// the index of statistic reusable rule in old circuit breaker slice
119+
reuseStatIdx = -1
120+
121+
for idx, oldTc := range oldResCbs {
122+
oldRule := oldTc.BoundRule()
123+
if oldRule.IsEqualsTo(r) {
124+
// break if there is equivalent rule
125+
equalIdx = idx
126+
break
127+
}
128+
// find the index of first StatReusable rule
129+
if !oldRule.IsStatReusable(r) {
130+
continue
131+
}
132+
if reuseStatIdx >= 0 {
133+
// had find reuse rule.
134+
continue
135+
}
136+
reuseStatIdx = idx
137+
}
138+
return equalIdx, reuseStatIdx
139+
}
140+
141+
func insertCbToCbMap(cb CircuitBreaker, res string, m map[string][]CircuitBreaker) {
142+
cbsOfRes, exists := m[res]
143+
if !exists {
144+
cbsOfRes = make([]CircuitBreaker, 0, 1)
145+
m[res] = append(cbsOfRes, cb)
146+
} else {
147+
m[res] = append(cbsOfRes, cb)
148+
}
149+
}
150+
109151
// Concurrent safe to update rules
110152
func onRuleUpdate(rules []Rule) (err error) {
111153
defer func() {
@@ -145,43 +187,19 @@ func onRuleUpdate(rules []Rule) (err error) {
145187
for res, resRules := range newBreakerRules {
146188
emptyCircuitBreakerList := make([]CircuitBreaker, 0, 0)
147189
for _, r := range resRules {
148-
// TODO: rearrange the code here.
149190
oldResCbs := breakers[res]
150191
if oldResCbs == nil {
151192
oldResCbs = emptyCircuitBreakerList
152193
}
153-
equalsIdx := -1
154-
reuseStatIdx := -1
155-
for idx, cb := range oldResCbs {
156-
oldRule := cb.BoundRule()
157-
if oldRule.IsEqualsTo(r) {
158-
equalsIdx = idx
159-
break
160-
}
161-
if !oldRule.IsStatReusable(r) {
162-
continue
163-
}
164-
if reuseStatIdx >= 0 {
165-
// had find reuse rule.
166-
continue
167-
}
168-
reuseStatIdx = idx
169-
}
194+
equalIdx, reuseStatIdx := calculateReuseIndexFor(r, oldResCbs)
170195

171196
// First check equals scenario
172-
if equalsIdx >= 0 {
197+
if equalIdx >= 0 {
173198
// reuse the old cb
174-
reuseOldCb := oldResCbs[equalsIdx]
175-
cbsOfRes, ok := newBreakers[res]
176-
if !ok {
177-
cbsOfRes = make([]CircuitBreaker, 0, 1)
178-
newBreakers[res] = append(cbsOfRes, reuseOldCb)
179-
} else {
180-
newBreakers[res] = append(cbsOfRes, reuseOldCb)
181-
}
199+
equalOldCb := oldResCbs[equalIdx]
200+
insertCbToCbMap(equalOldCb, res, newBreakers)
182201
// remove old cb from oldResCbs
183-
oldResCbs = append(oldResCbs[:equalsIdx], oldResCbs[equalsIdx+1:]...)
184-
breakers[res] = oldResCbs
202+
breakers[res] = append(oldResCbs[:equalIdx], oldResCbs[equalIdx+1:]...)
185203
continue
186204
}
187205

@@ -205,13 +223,7 @@ func onRuleUpdate(rules []Rule) (err error) {
205223
if reuseStatIdx >= 0 {
206224
breakers[res] = append(oldResCbs[:reuseStatIdx], oldResCbs[reuseStatIdx+1:]...)
207225
}
208-
cbsOfRes, ok := newBreakers[res]
209-
if !ok {
210-
cbsOfRes = make([]CircuitBreaker, 0, 1)
211-
newBreakers[res] = append(cbsOfRes, cb)
212-
} else {
213-
newBreakers[res] = append(cbsOfRes, cb)
214-
}
226+
insertCbToCbMap(cb, res, newBreakers)
215227
}
216228
}
217229

@@ -241,12 +253,14 @@ func rulesFrom(rm map[string][]Rule) []Rule {
241253
}
242254

243255
func logRuleUpdate(rules map[string][]Rule) {
244-
s, err := json.Marshal(rules)
245-
if err != nil {
246-
logger.Info("Circuit breaking rules loaded")
247-
} else {
248-
logger.Infof("Circuit breaking rules loaded: %s", s)
256+
sb := strings.Builder{}
257+
sb.WriteString("Circuit breaking rules loaded:[")
258+
259+
for _, r := range rulesFrom(rules) {
260+
sb.WriteString(r.String() + ",")
249261
}
262+
sb.WriteString("]")
263+
logger.Info(sb.String())
250264
}
251265

252266
func RegisterStateChangeListeners(listeners ...StateChangeListener) {

core/flow/rule.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,24 @@ type ClusterRuleConfig struct {
5858
// FlowRule describes the strategy of flow control.
5959
type FlowRule struct {
6060
// ID represents the unique ID of the rule (optional).
61-
ID uint64 `json:"id,omitempty"`
61+
ID uint64
6262

6363
// Resource represents the resource name.
64-
Resource string `json:"resource"`
64+
Resource string
6565
// LimitOrigin represents the target origin (reserved field).
66-
LimitOrigin string `json:"limitApp"`
67-
MetricType MetricType `json:"grade"`
66+
LimitOrigin string
67+
MetricType MetricType
6868
// Count represents the threshold.
69-
Count float64 `json:"count"`
70-
RelationStrategy RelationStrategy `json:"strategy"`
71-
ControlBehavior ControlBehavior `json:"controlBehavior"`
69+
Count float64
70+
RelationStrategy RelationStrategy
71+
ControlBehavior ControlBehavior
7272

73-
RefResource string `json:"refResource,omitempty"`
74-
WarmUpPeriodSec uint32 `json:"warmUpPeriodSec"`
75-
MaxQueueingTimeMs uint32 `json:"maxQueueingTimeMs"`
73+
RefResource string
74+
WarmUpPeriodSec uint32
75+
MaxQueueingTimeMs uint32
7676
// ClusterMode indicates whether the rule is for cluster flow control or local.
77-
ClusterMode bool `json:"clusterMode"`
78-
ClusterConfig ClusterRuleConfig `json:"clusterConfig"`
77+
ClusterMode bool
78+
ClusterConfig ClusterRuleConfig
7979
}
8080

8181
func (f *FlowRule) String() string {
File renamed without changes.

core/freq_params_traffic/concurrency_stat_slot.go core/hotspot/concurrency_stat_slot.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package freq_params_traffic
1+
package hotspot
22

33
import (
44
"github.com/alibaba/sentinel-golang/core/base"

core/freq_params_traffic/params_metric.go core/hotspot/params_metric.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package freq_params_traffic
1+
package hotspot
22

3-
import "github.com/alibaba/sentinel-golang/core/freq_params_traffic/cache"
3+
import "github.com/alibaba/sentinel-golang/core/hotspot/cache"
44

55
const (
66
ConcurrencyMaxCount = 4000

core/freq_params_traffic/rule.go core/hotspot/rule.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package freq_params_traffic
1+
package hotspot
22

33
import (
44
"fmt"
@@ -50,19 +50,19 @@ func (t MetricType) String() string {
5050
type ParamKind int
5151

5252
const (
53-
kindInt ParamKind = iota
54-
kindString
53+
KindInt ParamKind = iota
54+
KindString
5555
KindBool
5656
KindFloat64
5757
KindSum
5858
)
5959

6060
func (t ParamKind) String() string {
6161
switch t {
62-
case kindInt:
63-
return "kindInt"
64-
case kindString:
65-
return "kindString"
62+
case KindInt:
63+
return "KindInt"
64+
case KindString:
65+
return "KindString"
6666
case KindBool:
6767
return "KindBool"
6868
case KindFloat64:
@@ -102,7 +102,7 @@ type Rule struct {
102102
}
103103

104104
func (r *Rule) String() string {
105-
return fmt.Sprintf("{Id:%s, Resource:%s, MetricType:%+v, Behavior:%+v, ParamIndex:%d, Threshold:%f, MaxQueueingTimeMs:%d, BurstCount:%d, DurationInSec:%d, ParamsMaxCapacity:%d, SpecificItems:%+v},",
105+
return fmt.Sprintf("{Id:%s, Resource:%s, MetricType:%+v, Behavior:%+v, ParamIndex:%d, Threshold:%f, MaxQueueingTimeMs:%d, BurstCount:%d, DurationInSec:%d, ParamsMaxCapacity:%d, SpecificItems:%+v}",
106106
r.Id, r.Resource, r.MetricType, r.Behavior, r.ParamIndex, r.Threshold, r.MaxQueueingTimeMs, r.BurstCount, r.DurationInSec, r.ParamsMaxCapacity, r.SpecificItems)
107107
}
108108
func (r *Rule) ResourceName() string {
@@ -137,15 +137,15 @@ func parseSpecificItems(source map[SpecificValue]int64) map[interface{}]int64 {
137137
}
138138
for k, v := range source {
139139
switch k.ValKind {
140-
case kindInt:
140+
case KindInt:
141141
realVal, err := strconv.Atoi(k.ValStr)
142142
if err != nil {
143143
logger.Errorf("Fail to parse value for int specific item. paramKind: %+v, value: %s, err: %+v", k.ValKind, k.ValStr, err)
144144
continue
145145
}
146146
ret[realVal] = v
147147

148-
case kindString:
148+
case KindString:
149149
ret[k.ValStr] = v
150150

151151
case KindBool:

core/freq_params_traffic/rule_manager.go core/hotspot/rule_manager.go

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package freq_params_traffic
1+
package hotspot
22

33
import (
4-
"encoding/json"
54
"fmt"
5+
"strings"
66
"sync"
77

88
"github.com/alibaba/sentinel-golang/logging"
@@ -70,12 +70,16 @@ func LoadRules(rules []*Rule) (bool, error) {
7070
return true, err
7171
}
7272

73-
// GetRules return the whole of rules
74-
func GetRules() []*Rule {
73+
// GetRules return the res's rules
74+
func GetRules(res string) []*Rule {
7575
tcMux.RLock()
7676
defer tcMux.RUnlock()
77-
78-
return rulesFrom(tcMap)
77+
resTcs := tcMap[res]
78+
ret := make([]*Rule, 0, len(resTcs))
79+
for _, tc := range resTcs {
80+
ret = append(ret, tc.BoundRule())
81+
}
82+
return ret
7983
}
8084

8185
// ClearRules clears all rules in frequency parameters flow control components
@@ -106,12 +110,14 @@ func onRuleUpdate(rules []*Rule) (err error) {
106110
}
107111

108112
func logRuleUpdate(m trafficControllerMap) {
109-
s, err := json.Marshal(m)
110-
if err != nil {
111-
logger.Info("Frequency parameters flow control rules loaded")
112-
} else {
113-
logger.Infof("Frequency parameters flow control rules loaded: %s", s)
113+
sb := strings.Builder{}
114+
sb.WriteString("Frequency parameters flow control rules loaded:[")
115+
116+
for _, r := range rulesFrom(m) {
117+
sb.WriteString(r.String() + ",")
114118
}
119+
sb.WriteString("]")
120+
logger.Info(sb.String())
115121
}
116122

117123
func rulesFrom(m trafficControllerMap) []*Rule {

0 commit comments

Comments
 (0)