Skip to content

Commit 7eea8e8

Browse files
authored
Refine APIs of per-resource slot chain and improve rule slot registering logic in rule managers (#291)
* refine api and comments, and add unit tests
1 parent a9496ed commit 7eea8e8

File tree

11 files changed

+266
-78
lines changed

11 files changed

+266
-78
lines changed

api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.Blo
130130
if options.slotChain == nil {
131131
options.slotChain = misc.GetResourceSlotChain(resource)
132132
if options.slotChain == nil {
133-
options.slotChain = globalSlotChain
133+
options.slotChain = GlobalSlotChain()
134134
}
135135
}
136136
return entry(resource, options)

api/slot_chain.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,23 @@ func BuildDefaultSlotChain() *base.SlotChain {
3333
sc.AddStatSlotLast(circuitbreaker.DefaultMetricStatSlot)
3434
sc.AddStatSlotLast(hotspot.DefaultConcurrencyStatSlot)
3535
sc.AddStatSlotLast(flow.DefaultStandaloneStatSlot)
36-
37-
misc.RegisterCustomGlobalSlotsToSc(sc)
3836
return sc
3937
}
38+
39+
// RegisterGlobalStatPrepareSlot registers the global StatPrepareSlot for all resource
40+
// Note: this function is not thread-safe
41+
func RegisterGlobalStatPrepareSlot(slot base.StatPrepareSlot) {
42+
misc.RegisterGlobalStatPrepareSlot(slot)
43+
}
44+
45+
// RegisterGlobalRuleCheckSlot registers the global RuleCheckSlot for all resource
46+
// Note: this function is not thread-safe
47+
func RegisterGlobalRuleCheckSlot(slot base.RuleCheckSlot) {
48+
misc.RegisterGlobalRuleCheckSlot(slot)
49+
}
50+
51+
// RegisterGlobalStatSlot registers the global StatSlot for all resource
52+
// Note: this function is not thread-safe
53+
func RegisterGlobalStatSlot(slot base.StatSlot) {
54+
misc.RegisterGlobalStatSlot(slot)
55+
}

core/base/slot_chain.go

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ var (
8383

8484
func NewSlotChain() *SlotChain {
8585
return &SlotChain{
86-
statPres: make([]StatPrepareSlot, 0, 5),
87-
ruleChecks: make([]RuleCheckSlot, 0, 5),
88-
stats: make([]StatSlot, 0, 5),
86+
statPres: make([]StatPrepareSlot, 0, 8),
87+
ruleChecks: make([]RuleCheckSlot, 0, 8),
88+
stats: make([]StatSlot, 0, 8),
8989
ctxPool: ctxPool,
9090
}
9191
}
@@ -104,6 +104,21 @@ func (sc *SlotChain) RefurbishContext(c *EntryContext) {
104104
}
105105
}
106106

107+
// ValidateStatPrepareSlotNaming checks whether the name of StatPrepareSlot exists in SlotChain.[]StatPrepareSlot
108+
// return true the name of StatPrepareSlot doesn't exist in SlotChain.[]StatPrepareSlot
109+
func ValidateStatPrepareSlotNaming(sc *SlotChain, s StatPrepareSlot) bool {
110+
isValid := true
111+
f := func(slot StatPrepareSlot) {
112+
if slot.Name() == s.Name() {
113+
isValid = false
114+
}
115+
}
116+
sc.RangeStatPrepareSlot(f)
117+
118+
return isValid
119+
}
120+
121+
// RangeStatPrepareSlot iterates the SlotChain.[]StatPrepareSlot and call f function for each StatPrepareSlot
107122
func (sc *SlotChain) RangeStatPrepareSlot(f func(slot StatPrepareSlot)) {
108123
for _, slot := range sc.statPres {
109124
f(slot)
@@ -121,6 +136,21 @@ func (sc *SlotChain) AddStatPrepareSlotLast(s StatPrepareSlot) {
121136
sc.statPres = append(sc.statPres, s)
122137
}
123138

139+
// ValidateRuleCheckSlotNaming checks whether the name of RuleCheckSlot exists in SlotChain.[]RuleCheckSlot
140+
// return true the name of RuleCheckSlot doesn't exist in SlotChain.[]RuleCheckSlot
141+
func ValidateRuleCheckSlotNaming(sc *SlotChain, s RuleCheckSlot) bool {
142+
isValid := true
143+
f := func(slot RuleCheckSlot) {
144+
if slot.Name() == s.Name() {
145+
isValid = false
146+
}
147+
}
148+
sc.RangeRuleCheckSlot(f)
149+
150+
return isValid
151+
}
152+
153+
// RangeRuleCheckSlot iterates the SlotChain.[]RuleCheckSlot and call f function for each RuleCheckSlot
124154
func (sc *SlotChain) RangeRuleCheckSlot(f func(slot RuleCheckSlot)) {
125155
for _, slot := range sc.ruleChecks {
126156
f(slot)
@@ -137,6 +167,21 @@ func (sc *SlotChain) AddRuleCheckSlotLast(s RuleCheckSlot) {
137167
sc.ruleChecks = append(sc.ruleChecks, s)
138168
}
139169

170+
// ValidateStatSlotNaming checks whether the name of StatSlot exists in SlotChain.[]StatSlot
171+
// return true the name of StatSlot doesn't exist in SlotChain.[]StatSlot
172+
func ValidateStatSlotNaming(sc *SlotChain, s StatSlot) bool {
173+
isValid := true
174+
f := func(slot StatSlot) {
175+
if slot.Name() == s.Name() {
176+
isValid = false
177+
}
178+
}
179+
sc.RangeStatSlot(f)
180+
181+
return isValid
182+
}
183+
184+
// RangeStatSlot iterates the SlotChain.[]StatSlot and call f function for each StatSlot
140185
func (sc *SlotChain) RangeStatSlot(f func(slot StatSlot)) {
141186
for _, slot := range sc.stats {
142187
f(slot)

core/base/slot_chain_test.go

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package base
22

33
import (
4-
"fmt"
54
"reflect"
65
"strconv"
76
"testing"
@@ -16,11 +15,10 @@ type StatPrepareSlotMock1 struct {
1615
}
1716

1817
func (spl *StatPrepareSlotMock1) Name() string {
19-
return "mock-sentinel-prepare-slot1"
18+
return spl.name
2019
}
2120

2221
func (spl *StatPrepareSlotMock1) Prepare(ctx *EntryContext) {
23-
fmt.Println(spl.name)
2422
return
2523
}
2624

@@ -72,11 +70,10 @@ type RuleCheckSlotMock1 struct {
7270
}
7371

7472
func (rcs *RuleCheckSlotMock1) Name() string {
75-
return "mock-sentinel-rule-check-slot-1"
73+
return rcs.name
7674
}
7775

7876
func (rcs *RuleCheckSlotMock1) Check(ctx *EntryContext) *TokenResult {
79-
fmt.Println(rcs.name)
8077
return nil
8178
}
8279
func TestSlotChain_addRuleCheckSlotFirstAndLast(t *testing.T) {
@@ -127,17 +124,17 @@ type StatSlotMock1 struct {
127124
}
128125

129126
func (ss *StatSlotMock1) Name() string {
130-
return "mock-sentinel-stat-mock-slot-1"
127+
return ss.name
131128
}
132129

133130
func (ss *StatSlotMock1) OnEntryPassed(ctx *EntryContext) {
134-
fmt.Println(ss.name)
131+
return
135132
}
136133
func (ss *StatSlotMock1) OnEntryBlocked(ctx *EntryContext, blockError *BlockError) {
137-
fmt.Printf("%s blocked: %v\n", ss.name, blockError)
134+
return
138135
}
139136
func (ss *StatSlotMock1) OnCompleted(ctx *EntryContext) {
140-
fmt.Println(ss.name)
137+
return
141138
}
142139
func TestSlotChain_addStatSlotFirstAndLast(t *testing.T) {
143140
sc := NewSlotChain()
@@ -387,3 +384,90 @@ func TestSlotChain_Entry_With_Panic(t *testing.T) {
387384
ssm.AssertNumberOfCalls(t, "OnEntryPassed", 0)
388385
ssm.AssertNumberOfCalls(t, "OnEntryBlocked", 0)
389386
}
387+
388+
func TestValidateStatPrepareSlotNaming(t *testing.T) {
389+
sc := NewSlotChain()
390+
sps1 := &StatPrepareSlotMock1{
391+
name: "sps1",
392+
}
393+
sps2 := &StatPrepareSlotMock1{
394+
name: "sps2",
395+
}
396+
sps3 := &StatPrepareSlotMock1{
397+
name: "sps3",
398+
}
399+
sps4 := &StatPrepareSlotMock1{
400+
name: "sps4",
401+
}
402+
sc.AddStatPrepareSlotLast(sps1)
403+
sc.AddStatPrepareSlotLast(sps2)
404+
sc.AddStatPrepareSlotLast(sps3)
405+
sc.AddStatPrepareSlotLast(sps4)
406+
407+
sps5 := &StatPrepareSlotMock1{
408+
name: "sps5",
409+
}
410+
assert.True(t, ValidateStatPrepareSlotNaming(sc, sps5))
411+
sps6 := &StatPrepareSlotMock1{
412+
name: "sps1",
413+
}
414+
assert.True(t, !ValidateStatPrepareSlotNaming(sc, sps6))
415+
}
416+
417+
func TestValidateRuleCheckSlotNaming(t *testing.T) {
418+
sc := NewSlotChain()
419+
rcs1 := &RuleCheckSlotMock1{
420+
name: "rcs1",
421+
}
422+
rcs2 := &RuleCheckSlotMock1{
423+
name: "rcs2",
424+
}
425+
rcs3 := &RuleCheckSlotMock1{
426+
name: "rcs3",
427+
}
428+
rcs4 := &RuleCheckSlotMock1{
429+
name: "rcs4",
430+
}
431+
sc.AddRuleCheckSlotLast(rcs1)
432+
sc.AddRuleCheckSlotLast(rcs2)
433+
sc.AddRuleCheckSlotLast(rcs3)
434+
sc.AddRuleCheckSlotLast(rcs4)
435+
436+
rcs5 := &RuleCheckSlotMock1{
437+
name: "rcs5",
438+
}
439+
assert.True(t, ValidateRuleCheckSlotNaming(sc, rcs5))
440+
rcs6 := &RuleCheckSlotMock1{
441+
name: "rcs1",
442+
}
443+
assert.True(t, !ValidateRuleCheckSlotNaming(sc, rcs6))
444+
}
445+
446+
func TestValidateStatSlotNaming(t *testing.T) {
447+
sc := NewSlotChain()
448+
ss1 := &StatSlotMock1{
449+
name: "ss1",
450+
}
451+
ss2 := &StatSlotMock1{
452+
name: "ss2",
453+
}
454+
ss3 := &StatSlotMock1{
455+
name: "ss3",
456+
}
457+
ss4 := &StatSlotMock1{
458+
name: "ss4",
459+
}
460+
sc.AddStatSlotLast(ss1)
461+
sc.AddStatSlotLast(ss2)
462+
sc.AddStatSlotLast(ss3)
463+
sc.AddStatSlotLast(ss4)
464+
465+
ss5 := &StatSlotMock1{
466+
name: "ss5",
467+
}
468+
assert.True(t, ValidateStatSlotNaming(sc, ss5))
469+
ss6 := &StatSlotMock1{
470+
name: "ss1",
471+
}
472+
assert.True(t, !ValidateStatSlotNaming(sc, ss6))
473+
}

core/circuitbreaker/rule_manager.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,6 @@ func onRuleUpdate(rules []*Rule) (err error) {
198198
}
199199
ruleSet = append(ruleSet, rule)
200200
newBreakerRules[classification] = ruleSet
201-
202-
// update resource slot chain
203-
misc.RegisterResourceRuleCheckSlot(rule.Resource, DefaultSlot)
204-
misc.RegisterResourceStatSlot(rule.Resource, DefaultMetricStatSlot)
205201
}
206202

207203
newBreakers := make(map[string][]CircuitBreaker)
@@ -265,6 +261,14 @@ func onRuleUpdate(rules []*Rule) (err error) {
265261
}
266262
}
267263

264+
for res, cbs := range newBreakers {
265+
if len(cbs) > 0 {
266+
// update resource slot chain
267+
misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
268+
misc.RegisterStatSlotForResource(res, DefaultMetricStatSlot)
269+
}
270+
}
271+
268272
breakerRules = newBreakerRules
269273
breakers = newBreakers
270274
return nil

core/flow/rule_manager.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,6 @@ func onRuleUpdate(rules []*Rule) (err error) {
142142
resRules = make([]*Rule, 0, 1)
143143
}
144144
resRulesMap[rule.Resource] = append(resRules, rule)
145-
146-
// update resource slot chain
147-
misc.RegisterResourceRuleCheckSlot(rule.Resource, DefaultSlot)
148-
misc.RegisterResourceStatSlot(rule.Resource, DefaultStandaloneStatSlot)
149145
}
150146
m := make(TrafficControllerMap, len(resRulesMap))
151147
start := util.CurrentTimeNano()
@@ -161,6 +157,14 @@ func onRuleUpdate(rules []*Rule) (err error) {
161157
for res, rulesOfRes := range resRulesMap {
162158
m[res] = buildRulesOfRes(res, rulesOfRes)
163159
}
160+
161+
for res, tcs := range m {
162+
if len(tcs) > 0 {
163+
// update resource slot chain
164+
misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
165+
misc.RegisterStatSlotForResource(res, DefaultStandaloneStatSlot)
166+
}
167+
}
164168
tcMap = m
165169
return nil
166170
}

core/hotspot/rule_manager.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,6 @@ func onRuleUpdate(rules []*Rule) (err error) {
130130
}
131131
ruleSet = append(ruleSet, r)
132132
newRuleMap[res] = ruleSet
133-
134-
// update resource slot chain
135-
misc.RegisterResourceRuleCheckSlot(r.Resource, DefaultSlot)
136-
misc.RegisterResourceStatSlot(r.Resource, DefaultConcurrencyStatSlot)
137133
}
138134

139135
m := make(trafficControllerMap)
@@ -195,6 +191,13 @@ func onRuleUpdate(rules []*Rule) (err error) {
195191
insertTcToTcMap(tc, res, m)
196192
}
197193
}
194+
for res, tcs := range m {
195+
if len(tcs) > 0 {
196+
// update resource slot chain
197+
misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
198+
misc.RegisterStatSlotForResource(res, DefaultConcurrencyStatSlot)
199+
}
200+
}
198201
tcMap = m
199202

200203
return nil

core/isolation/rule_manager.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ func LoadRules(rules []*Rule) (updated bool, err error) {
3030
resRules = make([]*Rule, 0, 1)
3131
}
3232
m[r.Resource] = append(resRules, r)
33-
34-
// update resource slot chain
35-
misc.RegisterResourceRuleCheckSlot(r.Resource, DefaultSlot)
3633
}
3734

3835
start := util.CurrentTimeNano()
@@ -42,6 +39,13 @@ func LoadRules(rules []*Rule) (updated bool, err error) {
4239
logging.Debug("time statistic(ns) for updating isolation rule", "timeCost", util.CurrentTimeNano()-start)
4340
logRuleUpdate(m)
4441
}()
42+
43+
for res, rs := range m {
44+
if len(rs) > 0 {
45+
// update resource slot chain
46+
misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
47+
}
48+
}
4549
ruleMap = m
4650
return
4751
}

0 commit comments

Comments
 (0)