Repository: alibaba/sentinel-golang
Pull request #383 (2021-01-19 14:27:09)

Deprecated resource level slot chain
<!--  Thanks for submitting a pull request! Here are some tips for you:
1. Please make sure you have read and understood the contributing guidelines: https://github.com/alibaba/blob/master/CONTRIBUTING.md
2. Please make sure the PR has a corresponding issue.
-->

### Describe what this PR does / why we need it
deprecated resource slot chain

### Does this pull request fix one issue?

<!--If that, add "Fixes #xxxx" below in the next line. For example, Fixes #15. Otherwise, add "NONE" -->

### Describe how you did it


### Describe how to verify it


### Special notes for reviews


Patch:
diff --git a/api/api.go b/api/api.go
index 3e97032..f444fc5 100644
--- a/api/api.go
+++ b/api/api.go
@@ -18,7 +18,6 @@ import (
 	"sync"
 
 	"github.com/alibaba/sentinel-golang/core/base"
-	"github.com/alibaba/sentinel-golang/core/misc"
 )
 
 var entryOptsPool = sync.Pool{
@@ -142,10 +141,7 @@ func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.Blo
 		opt(options)
 	}
 	if options.slotChain == nil {
-		options.slotChain = misc.GetResourceSlotChain(resource)
-		if options.slotChain == nil {
-			options.slotChain = GlobalSlotChain()
-		}
+		options.slotChain = GlobalSlotChain()
 	}
 	return entry(resource, options)
 }
diff --git a/api/slot_chain.go b/api/slot_chain.go
index f95a8e5..35ae233 100644
--- a/api/slot_chain.go
+++ b/api/slot_chain.go
@@ -21,7 +21,6 @@ import (
 	"github.com/alibaba/sentinel-golang/core/hotspot"
 	"github.com/alibaba/sentinel-golang/core/isolation"
 	"github.com/alibaba/sentinel-golang/core/log"
-	"github.com/alibaba/sentinel-golang/core/misc"
 	"github.com/alibaba/sentinel-golang/core/stat"
 	"github.com/alibaba/sentinel-golang/core/system"
 )
@@ -49,21 +48,3 @@ func BuildDefaultSlotChain() *base.SlotChain {
 	sc.AddStatSlot(circuitbreaker.DefaultMetricStatSlot)
 	return sc
 }
-
-// RegisterGlobalStatPrepareSlot registers the global StatPrepareSlot for all resource
-// Note: this function is not thread-safe
-func RegisterGlobalStatPrepareSlot(slot base.StatPrepareSlot) {
-	misc.RegisterGlobalStatPrepareSlot(slot)
-}
-
-// RegisterGlobalRuleCheckSlot registers the global RuleCheckSlot for all resource
-// Note: this function is not thread-safe
-func RegisterGlobalRuleCheckSlot(slot base.RuleCheckSlot) {
-	misc.RegisterGlobalRuleCheckSlot(slot)
-}
-
-// RegisterGlobalStatSlot registers the global StatSlot for all resource
-// Note: this function is not thread-safe
-func RegisterGlobalStatSlot(slot base.StatSlot) {
-	misc.RegisterGlobalStatSlot(slot)
-}
diff --git a/core/base/slot_chain.go b/core/base/slot_chain.go
index 16b88d7..184e04d 100644
--- a/core/base/slot_chain.go
+++ b/core/base/slot_chain.go
@@ -24,9 +24,6 @@ import (
 )
 
 type BaseSlot interface {
-	// Name returns it's slot name which should be global unique.
-	Name() string
-
 	// Order returns the sort value of the slot.
 	// SlotChain will sort all it's slots by ascending sort value in each bucket
 	// (StatPrepareSlot bucket、RuleCheckSlot bucket and StatSlot bucket)
@@ -77,8 +74,6 @@ type StatSlot interface {
 // SlotChain hold all system slots and customized slot.
 // SlotChain support plug-in slots developed by developer.
 type SlotChain struct {
-	// RWMutex guard the slots in SlotChain and make sure the concurrency safe
-	sync.RWMutex
 	// statPres is in ascending order by StatPrepareSlot.Order() value.
 	statPres []StatPrepareSlot
 	// ruleChecks is in ascending order by RuleCheckSlot.Order() value.
@@ -108,7 +103,6 @@ var (
 
 func NewSlotChain() *SlotChain {
 	return &SlotChain{
-		RWMutex:    sync.RWMutex{},
 		statPres:   make([]StatPrepareSlot, 0, 8),
 		ruleChecks: make([]RuleCheckSlot, 0, 8),
 		stats:      make([]StatSlot, 0, 8),
@@ -130,31 +124,6 @@ func (sc *SlotChain) RefurbishContext(c *EntryContext) {
 	}
 }
 
-// ValidateStatPrepareSlotNaming checks whether the name of StatPrepareSlot exists in SlotChain.[]StatPrepareSlot
-// return true the name of StatPrepareSlot doesn't exist in SlotChain.[]StatPrepareSlot
-// ValidateStatPrepareSlotNaming is non-thread safe,
-// In concurrency scenario, ValidateStatPrepareSlotNaming must be guarded by SlotChain.RWMutex#RLock
-func ValidateStatPrepareSlotNaming(sc *SlotChain, s StatPrepareSlot) bool {
-	isValid := true
-	f := func(slot StatPrepareSlot) {
-		if slot.Name() == s.Name() {
-			isValid = false
-		}
-	}
-	sc.RangeStatPrepareSlot(f)
-
-	return isValid
-}
-
-// RangeStatPrepareSlot iterates the SlotChain.[]StatPrepareSlot and call f function for each StatPrepareSlot
-// RangeStatPrepareSlot is non-thread safe,
-// In concurrency scenario, RangeStatPrepareSlot must be guarded by SlotChain.RWMutex#RLock
-func (sc *SlotChain) RangeStatPrepareSlot(f func(slot StatPrepareSlot)) {
-	for _, slot := range sc.statPres {
-		f(slot)
-	}
-}
-
 // AddStatPrepareSlot adds the StatPrepareSlot slot to the StatPrepareSlot list of the SlotChain.
 // All StatPrepareSlot in the list will be sorted according to StatPrepareSlot.Order() in ascending order.
 // AddStatPrepareSlot is non-thread safe,
@@ -166,31 +135,6 @@ func (sc *SlotChain) AddStatPrepareSlot(s StatPrepareSlot) {
 	})
 }
 
-// ValidateRuleCheckSlotNaming checks whether the name of RuleCheckSlot exists in SlotChain.[]RuleCheckSlot
-// return true the name of RuleCheckSlot doesn't exist in SlotChain.[]RuleCheckSlot
-// ValidateRuleCheckSlotNaming is non-thread safe,
-// In concurrency scenario, ValidateRuleCheckSlotNaming must be guarded by SlotChain.RWMutex#RLock
-func ValidateRuleCheckSlotNaming(sc *SlotChain, s RuleCheckSlot) bool {
-	isValid := true
-	f := func(slot RuleCheckSlot) {
-		if slot.Name() == s.Name() {
-			isValid = false
-		}
-	}
-	sc.RangeRuleCheckSlot(f)
-
-	return isValid
-}
-
-// RangeRuleCheckSlot iterates the SlotChain.[]RuleCheckSlot and call f function for each RuleCheckSlot
-// RangeRuleCheckSlot is non-thread safe,
-// In concurrency scenario, RangeRuleCheckSlot must be guarded by SlotChain.RWMutex#RLock
-func (sc *SlotChain) RangeRuleCheckSlot(f func(slot RuleCheckSlot)) {
-	for _, slot := range sc.ruleChecks {
-		f(slot)
-	}
-}
-
 // AddRuleCheckSlot adds the RuleCheckSlot to the RuleCheckSlot list of the SlotChain.
 // All RuleCheckSlot in the list will be sorted according to RuleCheckSlot.Order() in ascending order.
 // AddRuleCheckSlot is non-thread safe,
@@ -202,31 +146,6 @@ func (sc *SlotChain) AddRuleCheckSlot(s RuleCheckSlot) {
 	})
 }
 
-// ValidateStatSlotNaming checks whether the name of StatSlot exists in SlotChain.[]StatSlot
-// return true the name of StatSlot doesn't exist in SlotChain.[]StatSlot
-// ValidateStatSlotNaming is non-thread safe,
-// In concurrency scenario, ValidateStatSlotNaming must be guarded by SlotChain.RWMutex#RLock
-func ValidateStatSlotNaming(sc *SlotChain, s StatSlot) bool {
-	isValid := true
-	f := func(slot StatSlot) {
-		if slot.Name() == s.Name() {
-			isValid = false
-		}
-	}
-	sc.RangeStatSlot(f)
-
-	return isValid
-}
-
-// RangeStatSlot iterates the SlotChain.[]StatSlot and call f function for each StatSlot
-// RangeStatSlot is non-thread safe,
-// In concurrency scenario, RangeStatSlot must be guarded by SlotChain.RWMutex#RLock
-func (sc *SlotChain) RangeStatSlot(f func(slot StatSlot)) {
-	for _, slot := range sc.stats {
-		f(slot)
-	}
-}
-
 // AddStatSlot adds the StatSlot to the StatSlot list of the SlotChain.
 // All StatSlot in the list will be sorted according to StatSlot.Order() in ascending order.
 // AddStatSlot is non-thread safe,
@@ -241,11 +160,9 @@ func (sc *SlotChain) AddStatSlot(s StatSlot) {
 // The entrance of slot chain
 // Return the TokenResult and nil if internal panic.
 func (sc *SlotChain) Entry(ctx *EntryContext) *TokenResult {
-	sc.RLock()
 	// This should not happen, unless there are errors existing in Sentinel internal.
 	// If happened, need to add TokenResult in EntryContext
 	defer func() {
-		sc.RUnlock()
 		if err := recover(); err != nil {
 			logging.Error(errors.Errorf("%+v", err), "Sentinel internal panic in SlotChain.Entry()")
 			ctx.SetError(errors.Errorf("%+v", err))
@@ -311,9 +228,6 @@ func (sc *SlotChain) exit(ctx *EntryContext) {
 	if ctx.IsBlocked() {
 		return
 	}
-
-	sc.RLock()
-	defer sc.RUnlock()
 	for _, s := range sc.stats {
 		s.OnCompleted(ctx)
 	}
diff --git a/core/circuitbreaker/rule_manager.go b/core/circuitbreaker/rule_manager.go
index 6b2ef91..781ed89 100644
--- a/core/circuitbreaker/rule_manager.go
+++ b/core/circuitbreaker/rule_manager.go
@@ -19,7 +19,6 @@ import (
 	"reflect"
 	"sync"
 
-	"github.com/alibaba/sentinel-golang/core/misc"
 	"github.com/alibaba/sentinel-golang/logging"
 	"github.com/alibaba/sentinel-golang/util"
 	"github.com/pkg/errors"
@@ -264,9 +263,6 @@ func onRuleUpdate(rawResRulesMap map[string][]*Rule) (err error) {
 		newCbsOfRes := buildResourceCircuitBreaker(res, resRules, breakersClone[res])
 		if len(newCbsOfRes) > 0 {
 			newBreakers[res] = newCbsOfRes
-			// update resource slot chain
-			misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-			misc.RegisterStatSlotForResource(res, DefaultMetricStatSlot)
 		}
 	}
 
@@ -309,12 +305,6 @@ func onResourceRuleUpdate(res string, rawResRules []*Rule) (err error) {
 
 	newCbsOfRes := buildResourceCircuitBreaker(res, rawResRules, oldResCbs)
 
-	if len(newCbsOfRes) > 0 {
-		// update resource slot chain
-		misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-		misc.RegisterStatSlotForResource(res, DefaultMetricStatSlot)
-	}
-
 	updateMux.Lock()
 	if len(newCbsOfRes) == 0 {
 		delete(breakerRules, res)
diff --git a/core/circuitbreaker/slot.go b/core/circuitbreaker/slot.go
index 3c7350e..1b57789 100644
--- a/core/circuitbreaker/slot.go
+++ b/core/circuitbreaker/slot.go
@@ -19,7 +19,6 @@ import (
 )
 
 const (
-	RuleCheckSlotName  = "sentinel-core-circuit-breaker-rule-check-slot"
 	RuleCheckSlotOrder = 5000
 )
 
@@ -30,10 +29,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return RuleCheckSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return RuleCheckSlotOrder
 }
diff --git a/core/circuitbreaker/stat_slot.go b/core/circuitbreaker/stat_slot.go
index e6dd55f..469d70d 100644
--- a/core/circuitbreaker/stat_slot.go
+++ b/core/circuitbreaker/stat_slot.go
@@ -19,7 +19,6 @@ import (
 )
 
 const (
-	StatSlotName  = "sentinel-core-circuit-breaker-metric-stat-slot"
 	StatSlotOrder = 5000
 )
 
@@ -32,10 +31,6 @@ var (
 type MetricStatSlot struct {
 }
 
-func (s *MetricStatSlot) Name() string {
-	return StatSlotName
-}
-
 func (s *MetricStatSlot) Order() uint32 {
 	return StatSlotOrder
 }
diff --git a/core/flow/rule_manager.go b/core/flow/rule_manager.go
index 4e5814a..9e0c9ba 100644
--- a/core/flow/rule_manager.go
+++ b/core/flow/rule_manager.go
@@ -21,7 +21,6 @@ import (
 
 	"github.com/alibaba/sentinel-golang/core/base"
 	"github.com/alibaba/sentinel-golang/core/config"
-	"github.com/alibaba/sentinel-golang/core/misc"
 	"github.com/alibaba/sentinel-golang/core/stat"
 	sbase "github.com/alibaba/sentinel-golang/core/stat/base"
 	"github.com/alibaba/sentinel-golang/core/system_metric"
@@ -221,14 +220,6 @@ func onRuleUpdate(rawResRulesMap map[string][]*Rule) (err error) {
 		}
 	}
 
-	for res, tcs := range m {
-		if len(tcs) > 0 {
-			// update resource slot chain
-			misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-			misc.RegisterStatSlotForResource(res, DefaultStandaloneStatSlot)
-		}
-	}
-
 	tcMux.Lock()
 	tcMap = m
 	tcMux.Unlock()
@@ -289,12 +280,6 @@ func onResourceRuleUpdate(res string, rawResRules []*Rule) (err error) {
 	tcMux.RUnlock()
 	newResTcs := buildResourceTrafficShapingController(res, validResRules, oldResTcs)
 
-	if len(newResTcs) > 0 {
-		// update resource slot chain
-		misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-		misc.RegisterStatSlotForResource(res, DefaultStandaloneStatSlot)
-	}
-
 	tcMux.Lock()
 	if len(newResTcs) == 0 {
 		delete(tcMap, res)
diff --git a/core/flow/slot.go b/core/flow/slot.go
index 4fc66fa..58a739f 100644
--- a/core/flow/slot.go
+++ b/core/flow/slot.go
@@ -23,7 +23,6 @@ import (
 )
 
 const (
-	RuleCheckSlotName  = "sentinel-core-flow-rule-check-slot"
 	RuleCheckSlotOrder = 2000
 )
 
@@ -34,10 +33,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return RuleCheckSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return RuleCheckSlotOrder
 }
diff --git a/core/flow/standalone_stat_slot.go b/core/flow/standalone_stat_slot.go
index 8ba7368..76c46f2 100644
--- a/core/flow/standalone_stat_slot.go
+++ b/core/flow/standalone_stat_slot.go
@@ -21,7 +21,6 @@ import (
 )
 
 const (
-	StatSlotName  = "sentinel-core-flow-standalone-stat-slot"
 	StatSlotOrder = 3000
 )
 
@@ -32,10 +31,6 @@ var (
 type StandaloneStatSlot struct {
 }
 
-func (s *StandaloneStatSlot) Name() string {
-	return StatSlotName
-}
-
 func (s *StandaloneStatSlot) Order() uint32 {
 	return StatSlotOrder
 }
diff --git a/core/hotspot/concurrency_stat_slot.go b/core/hotspot/concurrency_stat_slot.go
index 43d3c74..6d8e0a8 100644
--- a/core/hotspot/concurrency_stat_slot.go
+++ b/core/hotspot/concurrency_stat_slot.go
@@ -22,7 +22,6 @@ import (
 )
 
 const (
-	StatSlotName  = "sentinel-core-hotspot-concurrency-stat-slot"
 	StatSlotOrder = 4000
 )
 
@@ -34,10 +33,6 @@ var (
 type ConcurrencyStatSlot struct {
 }
 
-func (c *ConcurrencyStatSlot) Name() string {
-	return StatSlotName
-}
-
 func (s *ConcurrencyStatSlot) Order() uint32 {
 	return StatSlotOrder
 }
diff --git a/core/hotspot/rule_manager.go b/core/hotspot/rule_manager.go
index 26f478f..d061df4 100644
--- a/core/hotspot/rule_manager.go
+++ b/core/hotspot/rule_manager.go
@@ -19,7 +19,6 @@ import (
 	"reflect"
 	"sync"
 
-	"github.com/alibaba/sentinel-golang/core/misc"
 	"github.com/alibaba/sentinel-golang/logging"
 	"github.com/alibaba/sentinel-golang/util"
 	"github.com/pkg/errors"
@@ -195,19 +194,6 @@ func onRuleUpdate(rawResRulesMap map[string][]*Rule) (err error) {
 		m[res] = buildResourceTrafficShapingController(res, rules, tcMapClone[res])
 	}
 
-	for res, tcs := range m {
-		if len(tcs) > 0 {
-			// update resource slot chain
-			misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-			for _, tc := range tcs {
-				if tc.BoundRule().MetricType == Concurrency {
-					misc.RegisterStatSlotForResource(res, DefaultConcurrencyStatSlot)
-					break
-				}
-			}
-		}
-	}
-
 	tcMux.Lock()
 	tcMap = m
 	tcMux.Unlock()
@@ -246,16 +232,6 @@ func onResourceRuleUpdate(res string, rawResRules []*Rule) (err error) {
 	tcMux.RUnlock()
 
 	newResTcs := buildResourceTrafficShapingController(res, validResRules, oldResTcs)
-	if len(newResTcs) > 0 {
-		// update resource slot chain
-		misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-		for _, tc := range newResTcs {
-			if tc.BoundRule().MetricType == Concurrency {
-				misc.RegisterStatSlotForResource(res, DefaultConcurrencyStatSlot)
-				break
-			}
-		}
-	}
 
 	tcMux.Lock()
 	if len(newResTcs) == 0 {
diff --git a/core/hotspot/slot.go b/core/hotspot/slot.go
index f64e97c..d7edf1e 100644
--- a/core/hotspot/slot.go
+++ b/core/hotspot/slot.go
@@ -20,7 +20,6 @@ import (
 )
 
 const (
-	RuleCheckSlotName  = "sentinel-core-hotspot-rule-check-slot"
 	RuleCheckSlotOrder = 4000
 )
 
@@ -31,10 +30,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return RuleCheckSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return RuleCheckSlotOrder
 }
diff --git a/core/isolation/rule_manager.go b/core/isolation/rule_manager.go
index 6276c23..669ae61 100644
--- a/core/isolation/rule_manager.go
+++ b/core/isolation/rule_manager.go
@@ -18,7 +18,6 @@ import (
 	"reflect"
 	"sync"
 
-	"github.com/alibaba/sentinel-golang/core/misc"
 	"github.com/alibaba/sentinel-golang/logging"
 	"github.com/alibaba/sentinel-golang/util"
 	"github.com/pkg/errors"
@@ -72,13 +71,6 @@ func onRuleUpdate(rawResRulesMap map[string][]*Rule) (err error) {
 	}
 
 	start := util.CurrentTimeNano()
-
-	for res, rs := range validResRulesMap {
-		if len(rs) > 0 {
-			// update resource slot chain
-			misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-		}
-	}
 	rwMux.Lock()
 	ruleMap = validResRulesMap
 	rwMux.Unlock()
@@ -130,11 +122,6 @@ func onResourceRuleUpdate(res string, rawResRules []*Rule) (err error) {
 	}
 
 	start := util.CurrentTimeNano()
-	if len(validResRules) > 0 {
-		// update resource slot chain
-		misc.RegisterRuleCheckSlotForResource(res, DefaultSlot)
-	}
-
 	rwMux.Lock()
 	if len(validResRules) == 0 {
 		delete(ruleMap, res)
diff --git a/core/isolation/slot.go b/core/isolation/slot.go
index 6109a54..037991e 100644
--- a/core/isolation/slot.go
+++ b/core/isolation/slot.go
@@ -21,7 +21,6 @@ import (
 )
 
 const (
-	RuleCheckSlotName  = "sentinel-core-isolation-rule-check-slot"
 	RuleCheckSlotOrder = 3000
 )
 
@@ -32,10 +31,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return RuleCheckSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return RuleCheckSlotOrder
 }
diff --git a/core/log/slot.go b/core/log/slot.go
index 427aad9..d512f4d 100644
--- a/core/log/slot.go
+++ b/core/log/slot.go
@@ -19,7 +19,6 @@ import (
 )
 
 const (
-	StatSlotName  = "sentinel-core-log-stat-slot"
 	StatSlotOrder = 2000
 )
 
@@ -30,10 +29,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return StatSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return StatSlotOrder
 }
diff --git a/core/misc/resource_slot_chain.go b/core/misc/resource_slot_chain.go
deleted file mode 100644
index dc01aa3..0000000
--- a/core/misc/resource_slot_chain.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 1999-2020 Alibaba Group Holding Ltd.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package misc
-
-import (
-	"sync"
-
-	"github.com/alibaba/sentinel-golang/core/base"
-	"github.com/alibaba/sentinel-golang/core/log"
-	"github.com/alibaba/sentinel-golang/core/stat"
-	"github.com/alibaba/sentinel-golang/core/system"
-)
-
-var (
-	rsSlotChainLock sync.RWMutex
-	rsSlotChain     = make(map[string]*base.SlotChain, 8)
-
-	// non-thread safe
-	globalStatPrepareSlots = make([]base.StatPrepareSlot, 0, 8)
-	globalRuleCheckSlots   = make([]base.RuleCheckSlot, 0, 8)
-	globalStatSlot         = make([]base.StatSlot, 0, 8)
-)
-
-// non-thread safe
-func registerCustomGlobalSlotsToSc(sc *base.SlotChain) {
-	if sc == nil {
-		return
-	}
-	for _, s := range globalStatPrepareSlots {
-		if base.ValidateStatPrepareSlotNaming(sc, s) {
-			sc.AddStatPrepareSlot(s)
-		}
-	}
-	for _, s := range globalRuleCheckSlots {
-		if base.ValidateRuleCheckSlotNaming(sc, s) {
-			sc.AddRuleCheckSlot(s)
-		}
-	}
-	for _, s := range globalStatSlot {
-		if base.ValidateStatSlotNaming(sc, s) {
-			sc.AddStatSlot(s)
-		}
-	}
-}
-
-// RegisterGlobalStatPrepareSlot is not thread safe, and user must call RegisterGlobalStatPrepareSlot when initializing sentinel running environment
-func RegisterGlobalStatPrepareSlot(slot base.StatPrepareSlot) {
-	for _, s := range globalStatPrepareSlots {
-		if s.Name() == slot.Name() {
-			return
-		}
-	}
-	globalStatPrepareSlots = append(globalStatPrepareSlots, slot)
-}
-
-// RegisterGlobalRuleCheckSlot is not thread safe, and user must call RegisterGlobalRuleCheckSlot when initializing sentinel running environment
-func RegisterGlobalRuleCheckSlot(slot base.RuleCheckSlot) {
-	for _, s := range globalRuleCheckSlots {
-		if s.Name() == slot.Name() {
-			return
-		}
-	}
-	globalRuleCheckSlots = append(globalRuleCheckSlots, slot)
-}
-
-// RegisterGlobalStatSlot is not thread safe, and user must call RegisterGlobalStatSlot when initializing sentinel running environment
-func RegisterGlobalStatSlot(slot base.StatSlot) {
-	for _, s := range globalStatSlot {
-		if s.Name() == slot.Name() {
-			return
-		}
-	}
-	globalStatSlot = append(globalStatSlot, slot)
-}
-
-func newResourceSlotChain() *base.SlotChain {
-	sc := base.NewSlotChain()
-	sc.AddStatPrepareSlot(stat.DefaultResourceNodePrepareSlot)
-
-	sc.AddRuleCheckSlot(system.DefaultAdaptiveSlot)
-
-	sc.AddStatSlot(stat.DefaultSlot)
-	sc.AddStatSlot(log.DefaultSlot)
-	registerCustomGlobalSlotsToSc(sc)
-	return sc
-}
-
-func RegisterStatPrepareSlotForResource(rsName string, slot base.StatPrepareSlot) {
-	rsSlotChainLock.Lock()
-	defer rsSlotChainLock.Unlock()
-
-	sc, ok := rsSlotChain[rsName]
-	if !ok {
-		sc = newResourceSlotChain()
-		if base.ValidateStatPrepareSlotNaming(sc, slot) {
-			sc.AddStatPrepareSlot(slot)
-		}
-		rsSlotChain[rsName] = sc
-	} else {
-		sc.Lock()
-		if base.ValidateStatPrepareSlotNaming(sc, slot) {
-			sc.AddStatPrepareSlot(slot)
-		}
-		sc.Unlock()
-	}
-}
-
-func RegisterRuleCheckSlotForResource(rsName string, slot base.RuleCheckSlot) {
-	rsSlotChainLock.Lock()
-	defer rsSlotChainLock.Unlock()
-
-	sc, ok := rsSlotChain[rsName]
-	if !ok {
-		sc = newResourceSlotChain()
-		if base.ValidateRuleCheckSlotNaming(sc, slot) {
-			sc.AddRuleCheckSlot(slot)
-		}
-		rsSlotChain[rsName] = sc
-	} else {
-		sc.Lock()
-		if base.ValidateRuleCheckSlotNaming(sc, slot) {
-			sc.AddRuleCheckSlot(slot)
-		}
-		sc.Unlock()
-	}
-
-}
-
-func RegisterStatSlotForResource(rsName string, slot base.StatSlot) {
-	rsSlotChainLock.Lock()
-	defer rsSlotChainLock.Unlock()
-
-	sc, ok := rsSlotChain[rsName]
-	if !ok {
-		sc = newResourceSlotChain()
-		if base.ValidateStatSlotNaming(sc, slot) {
-			sc.AddStatSlot(slot)
-		}
-		rsSlotChain[rsName] = sc
-	} else {
-		sc.Lock()
-		if base.ValidateStatSlotNaming(sc, slot) {
-			sc.AddStatSlot(slot)
-		}
-		sc.Unlock()
-	}
-
-}
-
-func GetResourceSlotChain(rsName string) *base.SlotChain {
-	rsSlotChainLock.RLock()
-	defer rsSlotChainLock.RUnlock()
-
-	sc, ok := rsSlotChain[rsName]
-	if !ok {
-		return nil
-	}
-
-	return sc
-}
diff --git a/core/stat/stat_prepare_slot.go b/core/stat/stat_prepare_slot.go
index 79d3327..02fe6e0 100644
--- a/core/stat/stat_prepare_slot.go
+++ b/core/stat/stat_prepare_slot.go
@@ -19,7 +19,6 @@ import (
 )
 
 const (
-	PrepareSlotName  = "sentinel-core-stat-resource-node-prepare-slot"
 	PrepareSlotOrder = 1000
 )
 
@@ -30,10 +29,6 @@ var (
 type ResourceNodePrepareSlot struct {
 }
 
-func (s *ResourceNodePrepareSlot) Name() string {
-	return PrepareSlotName
-}
-
 func (s *ResourceNodePrepareSlot) Order() uint32 {
 	return PrepareSlotOrder
 }
diff --git a/core/stat/stat_slot.go b/core/stat/stat_slot.go
index 89ca577..ea66170 100644
--- a/core/stat/stat_slot.go
+++ b/core/stat/stat_slot.go
@@ -20,7 +20,6 @@ import (
 )
 
 const (
-	StatSlotName  = "sentinel-core-stat-slot"
 	StatSlotOrder = 1000
 )
 
@@ -31,10 +30,6 @@ var (
 type Slot struct {
 }
 
-func (s *Slot) Name() string {
-	return StatSlotName
-}
-
 func (s *Slot) Order() uint32 {
 	return StatSlotOrder
 }
diff --git a/core/system/slot.go b/core/system/slot.go
index e4c0888..5871ddc 100644
--- a/core/system/slot.go
+++ b/core/system/slot.go
@@ -21,7 +21,6 @@ import (
 )
 
 const (
-	RuleCheckSlotName  = "sentinel-core-system-adaptive-rule-check-slot"
 	RuleCheckSlotOrder = 1000
 )
 
@@ -32,10 +31,6 @@ var (
 type AdaptiveSlot struct {
 }
 
-func (s *AdaptiveSlot) Name() string {
-	return RuleCheckSlotName
-}
-
 func (s *AdaptiveSlot) Order() uint32 {
 	return RuleCheckSlotOrder
 }


Test patch:
diff --git a/api/api_test.go b/api/api_test.go
index 3849382..cb38e29 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -26,10 +26,6 @@ type prepareSlotMock struct {
 	mock.Mock
 }
 
-func (m *prepareSlotMock) Name() string {
-	return "mock-sentinel-prepare-slot"
-}
-
 func (m *prepareSlotMock) Order() uint32 {
 	return 0
 }
@@ -43,10 +39,6 @@ type mockRuleCheckSlot1 struct {
 	mock.Mock
 }
 
-func (m *mockRuleCheckSlot1) Name() string {
-	return "mock-sentinel-rule-check-slot1"
-}
-
 func (m *mockRuleCheckSlot1) Order() uint32 {
 	return 0
 }
@@ -60,10 +52,6 @@ type mockRuleCheckSlot2 struct {
 	mock.Mock
 }
 
-func (m *mockRuleCheckSlot2) Name() string {
-	return "mock-sentinel-rule-check-slot2"
-}
-
 func (m *mockRuleCheckSlot2) Order() uint32 {
 	return 0
 }
@@ -77,10 +65,6 @@ type statisticSlotMock struct {
 	mock.Mock
 }
 
-func (m *statisticSlotMock) Name() string {
-	return "mock-sentinel-stat-check-slot"
-}
-
 func (m *statisticSlotMock) Order() uint32 {
 	return 0
 }
diff --git a/core/base/slot_chain_test.go b/core/base/slot_chain_test.go
index 73f1e21..9fa8f64 100644
--- a/core/base/slot_chain_test.go
+++ b/core/base/slot_chain_test.go
@@ -30,10 +30,6 @@ type StatPrepareSlotMock1 struct {
 	order uint32
 }
 
-func (spl *StatPrepareSlotMock1) Name() string {
-	return spl.name
-}
-
 func (spl *StatPrepareSlotMock1) Order() uint32 {
 	return spl.order
 }
@@ -95,10 +91,6 @@ type RuleCheckSlotMock1 struct {
 	order uint32
 }
 
-func (rcs *RuleCheckSlotMock1) Name() string {
-	return rcs.name
-}
-
 func (rcs *RuleCheckSlotMock1) Order() uint32 {
 	return rcs.order
 }
@@ -159,10 +151,6 @@ type StatSlotMock1 struct {
 	order uint32
 }
 
-func (ss *StatSlotMock1) Name() string {
-	return ss.name
-}
-
 func (ss *StatSlotMock1) Order() uint32 {
 	return ss.order
 }
@@ -229,10 +217,6 @@ type prepareSlotMock struct {
 	mock.Mock
 }
 
-func (m *prepareSlotMock) Name() string {
-	return "mock-sentinel-prepare-slot-1"
-}
-
 func (m *prepareSlotMock) Order() uint32 {
 	return 0
 }
@@ -246,10 +230,6 @@ type mockRuleCheckSlot1 struct {
 	mock.Mock
 }
 
-func (m *mockRuleCheckSlot1) Name() string {
-	return "mock-sentinel-check-slot--1"
-}
-
 func (m *mockRuleCheckSlot1) Order() uint32 {
 	return 0
 }
@@ -263,10 +243,6 @@ type mockRuleCheckSlot2 struct {
 	mock.Mock
 }
 
-func (m *mockRuleCheckSlot2) Name() string {
-	return "mock-sentinel-rule-check-slot-2"
-}
-
 func (m *mockRuleCheckSlot2) Order() uint32 {
 	return 0
 }
@@ -280,10 +256,6 @@ type statisticSlotMock struct {
 	mock.Mock
 }
 
-func (m *statisticSlotMock) Name() string {
-	return "mock-sentinel-statistic-slot"
-}
-
 func (m *statisticSlotMock) Order() uint32 {
 	return 0
 }
@@ -398,10 +370,6 @@ type badPrepareSlotMock struct {
 	mock.Mock
 }
 
-func (m *badPrepareSlotMock) Name() string {
-	return "bad-mock-sentinel-prepare-slot"
-}
-
 func (m *badPrepareSlotMock) Order() uint32 {
 	return 0
 }
@@ -451,90 +419,3 @@ func TestSlotChain_Entry_With_Panic(t *testing.T) {
 	ssm.AssertNumberOfCalls(t, "OnEntryPassed", 0)
 	ssm.AssertNumberOfCalls(t, "OnEntryBlocked", 0)
 }
-
-func TestValidateStatPrepareSlotNaming(t *testing.T) {
-	sc := NewSlotChain()
-	sps1 := &StatPrepareSlotMock1{
-		name: "sps1",
-	}
-	sps2 := &StatPrepareSlotMock1{
-		name: "sps2",
-	}
-	sps3 := &StatPrepareSlotMock1{
-		name: "sps3",
-	}
-	sps4 := &StatPrepareSlotMock1{
-		name: "sps4",
-	}
-	sc.AddStatPrepareSlot(sps1)
-	sc.AddStatPrepareSlot(sps2)
-	sc.AddStatPrepareSlot(sps3)
-	sc.AddStatPrepareSlot(sps4)
-
-	sps5 := &StatPrepareSlotMock1{
-		name: "sps5",
-	}
-	assert.True(t, ValidateStatPrepareSlotNaming(sc, sps5))
-	sps6 := &StatPrepareSlotMock1{
-		name: "sps1",
-	}
-	assert.True(t, !ValidateStatPrepareSlotNaming(sc, sps6))
-}
-
-func TestValidateRuleCheckSlotNaming(t *testing.T) {
-	sc := NewSlotChain()
-	rcs1 := &RuleCheckSlotMock1{
-		name: "rcs1",
-	}
-	rcs2 := &RuleCheckSlotMock1{
-		name: "rcs2",
-	}
-	rcs3 := &RuleCheckSlotMock1{
-		name: "rcs3",
-	}
-	rcs4 := &RuleCheckSlotMock1{
-		name: "rcs4",
-	}
-	sc.AddRuleCheckSlot(rcs1)
-	sc.AddRuleCheckSlot(rcs2)
-	sc.AddRuleCheckSlot(rcs3)
-	sc.AddRuleCheckSlot(rcs4)
-
-	rcs5 := &RuleCheckSlotMock1{
-		name: "rcs5",
-	}
-	assert.True(t, ValidateRuleCheckSlotNaming(sc, rcs5))
-	rcs6 := &RuleCheckSlotMock1{
-		name: "rcs1",
-	}
-	assert.True(t, !ValidateRuleCheckSlotNaming(sc, rcs6))
-}
-
-func TestValidateStatSlotNaming(t *testing.T) {
-	sc := NewSlotChain()
-	ss1 := &StatSlotMock1{
-		name: "ss1",
-	}
-	ss2 := &StatSlotMock1{
-		name: "ss2",
-	}
-	ss3 := &StatSlotMock1{
-		name: "ss3",
-	}
-	ss4 := &StatSlotMock1{
-		name: "ss4",
-	}
-	sc.AddStatSlot(ss1)
-	sc.AddStatSlot(ss2)
-	sc.AddStatSlot(ss3)
-	sc.AddStatSlot(ss4)
-
-	ss5 := &StatSlotMock1{
-		name: "ss5",
-	}
-	assert.True(t, ValidateStatSlotNaming(sc, ss5))
-	ss6 := &StatSlotMock1{
-		name: "ss1",
-	}
-	assert.True(t, !ValidateStatSlotNaming(sc, ss6))
-}
diff --git a/core/log/metric/aggregator_test.go b/core/log/metric/aggregator_test.go
index f3de766..953f084 100644
--- a/core/log/metric/aggregator_test.go
+++ b/core/log/metric/aggregator_test.go
@@ -16,9 +16,11 @@ package metric
 
 import (
 	"testing"
+	"time"
 
 	"github.com/alibaba/sentinel-golang/core/base"
 	"github.com/alibaba/sentinel-golang/core/stat"
+	"github.com/alibaba/sentinel-golang/util"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/mock"
 )
@@ -266,3 +268,43 @@ func Test_currentMetricItems(t *testing.T) {
 		})
 	}
 }
+
+type writeData struct {
+	ts    uint64
+	items []*base.MetricItem
+}
+
+type MockMetricLogWriter struct {
+	dataChan chan *writeData
+}
+
+func (sw *MockMetricLogWriter) Write(ts uint64, items []*base.MetricItem) error {
+	sw.dataChan <- &writeData{ts, items}
+	return nil
+}
+
+func Test_Aggregate(t *testing.T) {
+	t.Run("Test_aggregate", func(t *testing.T) {
+		util.SetClock(util.NewMockClock())
+		m := &MockMetricLogWriter{make(chan *writeData, 100)}
+		err := InitTask()
+		metricWriter = m
+		assert.True(t, err == nil)
+		node := stat.GetOrCreateResourceNode("test", base.ResTypeCommon)
+		node.AddCount(base.MetricEventPass, 2)
+		node.AddCount(base.MetricEventBlock, 3)
+
+		util.Sleep(time.Duration(1) * time.Second)
+		data := <-m.dataChan
+		assert.True(t, data.items[0].Resource == "test")
+		assert.True(t, data.items[0].BlockQps == 3)
+		assert.True(t, data.items[0].PassQps == 2)
+		node.AddCount(base.MetricEventBlock, 3)
+
+		util.Sleep(time.Duration(1) * time.Second)
+		data2 := <-m.dataChan
+		assert.True(t, data2.ts-data.ts < 1100)
+		assert.True(t, data2.items[0].BlockQps == 3)
+		assert.True(t, data2.items[0].Resource == "test")
+	})
+}
diff --git a/core/misc/resource_slot_chain_test.go b/core/misc/resource_slot_chain_test.go
deleted file mode 100644
index 6f7d47c..0000000
--- a/core/misc/resource_slot_chain_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 1999-2020 Alibaba Group Holding Ltd.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package misc
-
-import (
-	"reflect"
-	"testing"
-
-	"github.com/alibaba/sentinel-golang/core/base"
-	"github.com/alibaba/sentinel-golang/core/system"
-	"github.com/stretchr/testify/assert"
-)
-
-type RuleCheckSlotMock1 struct {
-	name string
-}
-
-func (rcs *RuleCheckSlotMock1) Name() string {
-	return rcs.name
-}
-
-func (rcs *RuleCheckSlotMock1) Order() uint32 {
-	return 0
-}
-
-func (rcs *RuleCheckSlotMock1) Check(ctx *base.EntryContext) *base.TokenResult {
-	return nil
-}
-
-func TestRegisterRuleCheckSlotForResource(t *testing.T) {
-	rcs1 := &RuleCheckSlotMock1{
-		name: "rcs1",
-	}
-	rcs2 := &RuleCheckSlotMock1{
-		name: "rcs2",
-	}
-	rcs3 := &RuleCheckSlotMock1{
-		name: "rcs3",
-	}
-	rcs4 := &RuleCheckSlotMock1{
-		name: "rcs3",
-	}
-
-	assert.True(t, GetResourceSlotChain("abc0") == nil)
-	RegisterRuleCheckSlotForResource("abc", rcs1)
-	assert.True(t, GetResourceSlotChain("abc") != nil)
-	cnt := 0
-	GetResourceSlotChain("abc").RangeRuleCheckSlot(func(slot base.RuleCheckSlot) {
-		cnt++
-	})
-	assert.True(t, cnt == 2)
-
-	RegisterRuleCheckSlotForResource("abc", rcs2)
-	RegisterRuleCheckSlotForResource("abc", rcs3)
-	cnt2 := 0
-	GetResourceSlotChain("abc").RangeRuleCheckSlot(func(slot base.RuleCheckSlot) {
-		cnt2++
-	})
-	assert.True(t, cnt2 == 4)
-
-	RegisterRuleCheckSlotForResource("abc", rcs4)
-	cnt3 := 0
-	names := make([]string, 0, 4)
-	GetResourceSlotChain("abc").RangeRuleCheckSlot(func(slot base.RuleCheckSlot) {
-		cnt3++
-		names = append(names, slot.Name())
-	})
-	assert.True(t, reflect.DeepEqual(names, []string{"rcs1", "rcs2", "rcs3", system.RuleCheckSlotName}))
-	assert.True(t, cnt3 == 4)
-}
diff --git a/tests/core/misc/flow_slot_load_rule_test.go b/tests/core/misc/flow_slot_load_rule_test.go
deleted file mode 100644
index cb98f77..0000000
--- a/tests/core/misc/flow_slot_load_rule_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 1999-2020 Alibaba Group Holding Ltd.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package misc
-
-import (
-	"log"
-	"testing"
-	"time"
-
-	sentinel "github.com/alibaba/sentinel-golang/api"
-	"github.com/alibaba/sentinel-golang/core/base"
-	"github.com/alibaba/sentinel-golang/core/circuitbreaker"
-	"github.com/alibaba/sentinel-golang/core/config"
-	"github.com/alibaba/sentinel-golang/core/flow"
-	"github.com/alibaba/sentinel-golang/logging"
-	"github.com/alibaba/sentinel-golang/util"
-)
-
-func Test_Flow_Slot_LoadRules(t *testing.T) {
-	// We should initialize Sentinel first.
-	conf := config.NewDefaultConfig()
-	// for testing, logging output to console
-	conf.Sentinel.Log.Logger = logging.NewConsoleLogger()
-	err := sentinel.InitWithConfig(conf)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	_, err = flow.LoadRules([]*flow.Rule{
-		{
-			Resource:               "abc",
-			TokenCalculateStrategy: flow.Direct,
-			ControlBehavior:        flow.Reject,
-			Threshold:              10,
-			StatIntervalInMs:       1000,
-		},
-	})
-	if err != nil {
-		log.Fatalf("Unexpected error: %+v", err)
-		return
-	}
-
-	go func() {
-		util.Sleep(time.Second * 2)
-		_, err = circuitbreaker.LoadRules([]*circuitbreaker.Rule{
-			// Statistic time span=10s, recoveryTimeout=3s, slowRtUpperBound=50ms, maxSlowRequestRatio=50%
-			{
-				Resource:         "abc",
-				Strategy:         circuitbreaker.SlowRequestRatio,
-				RetryTimeoutMs:   3000,
-				MinRequestAmount: 10,
-				StatIntervalMs:   5000,
-				MaxAllowedRtMs:   50,
-				Threshold:        0.5,
-			},
-		})
-		if err != nil {
-			log.Fatal(err)
-		}
-	}()
-
-	for i := 0; i < 10; i++ {
-		go func() {
-			for {
-				e, b := sentinel.Entry("abc", sentinel.WithTrafficType(base.Inbound))
-				if b != nil {
-					// Blocked. We could get the block reason from the BlockError.
-				} else {
-					// Passed, wrap the logic here.
-					e.Exit()
-				}
-
-			}
-		}()
-	}
-
-	util.Sleep(time.Second * 3)
-}