Skip to content
Snippets Groups Projects
Commit 1b444d62 authored by Xin.Zh's avatar Xin.Zh Committed by GitHub
Browse files

Merge pull request #280 from flycash/feature/StrategyCreator

Ftr: Replace func(int, int) with TpsLimitStrategyCreator interface
parents d0f7561e a6533283
No related branches found
No related tags found
No related merge requests found
...@@ -22,7 +22,7 @@ import ( ...@@ -22,7 +22,7 @@ import (
) )
var ( var (
tpsLimitStrategy = make(map[string]func(rate int, interval int) tps.TpsLimitStrategy) tpsLimitStrategy = make(map[string]tps.TpsLimitStrategyCreator)
tpsLimiter = make(map[string]func() tps.TpsLimiter) tpsLimiter = make(map[string]func() tps.TpsLimiter)
) )
...@@ -39,11 +39,11 @@ func GetTpsLimiter(name string) tps.TpsLimiter { ...@@ -39,11 +39,11 @@ func GetTpsLimiter(name string) tps.TpsLimiter {
return creator() return creator()
} }
func SetTpsLimitStrategy(name string, creator func(rate int, interval int) tps.TpsLimitStrategy) { func SetTpsLimitStrategy(name string, creator tps.TpsLimitStrategyCreator) {
tpsLimitStrategy[name] = creator tpsLimitStrategy[name] = creator
} }
func GetTpsLimitStrategyCreator(name string) func(rate int, interval int) tps.TpsLimitStrategy { func GetTpsLimitStrategyCreator(name string) tps.TpsLimitStrategyCreator {
creator, ok := tpsLimitStrategy[name] creator, ok := tpsLimitStrategy[name]
if !ok { if !ok {
panic("TpsLimitStrategy for " + name + " is not existing, make sure you have import the package " + panic("TpsLimitStrategy for " + name + " is not existing, make sure you have import the package " +
......
...@@ -33,8 +33,9 @@ const ( ...@@ -33,8 +33,9 @@ const (
) )
func init() { func init() {
extension.SetTpsLimitStrategy(FixedWindowKey, NewFixedWindowTpsLimitStrategyImpl) creator := &fixedWindowStrategyCreator{}
extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, NewFixedWindowTpsLimitStrategyImpl) extension.SetTpsLimitStrategy(FixedWindowKey, creator)
extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, creator)
} }
/** /**
...@@ -76,7 +77,9 @@ func (impl *FixedWindowTpsLimitStrategyImpl) IsAllowable() bool { ...@@ -76,7 +77,9 @@ func (impl *FixedWindowTpsLimitStrategyImpl) IsAllowable() bool {
return atomic.AddInt32(&impl.count, 1) <= impl.rate return atomic.AddInt32(&impl.count, 1) <= impl.rate
} }
func NewFixedWindowTpsLimitStrategyImpl(rate int, interval int) tps.TpsLimitStrategy { type fixedWindowStrategyCreator struct{}
func (creator *fixedWindowStrategyCreator) Create(rate int, interval int) tps.TpsLimitStrategy {
return &FixedWindowTpsLimitStrategyImpl{ return &FixedWindowTpsLimitStrategyImpl{
rate: int32(rate), rate: int32(rate),
interval: int64(interval) * int64(time.Millisecond), // convert to ns interval: int64(interval) * int64(time.Millisecond), // convert to ns
......
...@@ -27,12 +27,13 @@ import ( ...@@ -27,12 +27,13 @@ import (
) )
func TestFixedWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) { func TestFixedWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) {
strategy := NewFixedWindowTpsLimitStrategyImpl(2, 60000) creator := &fixedWindowStrategyCreator{}
strategy := creator.Create(2, 60000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
strategy = NewFixedWindowTpsLimitStrategyImpl(2, 2000) strategy = creator.Create(2, 2000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
......
...@@ -29,7 +29,7 @@ import ( ...@@ -29,7 +29,7 @@ import (
) )
func init() { func init() {
extension.SetTpsLimitStrategy("slidingWindow", NewSlidingWindowTpsLimitStrategyImpl) extension.SetTpsLimitStrategy("slidingWindow", &slidingWindowStrategyCreator{})
} }
/** /**
...@@ -80,7 +80,9 @@ func (impl *SlidingWindowTpsLimitStrategyImpl) IsAllowable() bool { ...@@ -80,7 +80,9 @@ func (impl *SlidingWindowTpsLimitStrategyImpl) IsAllowable() bool {
return false return false
} }
func NewSlidingWindowTpsLimitStrategyImpl(rate int, interval int) tps.TpsLimitStrategy { type slidingWindowStrategyCreator struct{}
func (creator *slidingWindowStrategyCreator) Create(rate int, interval int) tps.TpsLimitStrategy {
return &SlidingWindowTpsLimitStrategyImpl{ return &SlidingWindowTpsLimitStrategyImpl{
rate: rate, rate: rate,
interval: int64(interval) * int64(time.Millisecond), interval: int64(interval) * int64(time.Millisecond),
......
...@@ -27,14 +27,15 @@ import ( ...@@ -27,14 +27,15 @@ import (
) )
func TestSlidingWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) { func TestSlidingWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) {
strategy := NewSlidingWindowTpsLimitStrategyImpl(2, 60000) creator := &slidingWindowStrategyCreator{}
strategy := creator.Create(2, 60000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
time.Sleep(2100 * time.Millisecond) time.Sleep(2100 * time.Millisecond)
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
strategy = NewSlidingWindowTpsLimitStrategyImpl(2, 2000) strategy = creator.Create(2, 2000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
......
...@@ -27,7 +27,9 @@ import ( ...@@ -27,7 +27,9 @@ import (
) )
func init() { func init() {
extension.SetTpsLimitStrategy("threadSafeFixedWindow", NewThreadSafeFixedWindowTpsLimitStrategyImpl) extension.SetTpsLimitStrategy("threadSafeFixedWindow", &threadSafeFixedWindowStrategyCreator{
fixedWindowStrategyCreator: &fixedWindowStrategyCreator{},
})
} }
/** /**
...@@ -56,8 +58,12 @@ func (impl *ThreadSafeFixedWindowTpsLimitStrategyImpl) IsAllowable() bool { ...@@ -56,8 +58,12 @@ func (impl *ThreadSafeFixedWindowTpsLimitStrategyImpl) IsAllowable() bool {
return impl.fixedWindow.IsAllowable() return impl.fixedWindow.IsAllowable()
} }
func NewThreadSafeFixedWindowTpsLimitStrategyImpl(rate int, interval int) tps.TpsLimitStrategy { type threadSafeFixedWindowStrategyCreator struct {
fixedWindowStrategy := NewFixedWindowTpsLimitStrategyImpl(rate, interval).(*FixedWindowTpsLimitStrategyImpl) fixedWindowStrategyCreator *fixedWindowStrategyCreator
}
func (creator *threadSafeFixedWindowStrategyCreator) Create(rate int, interval int) tps.TpsLimitStrategy {
fixedWindowStrategy := creator.fixedWindowStrategyCreator.Create(rate, interval).(*FixedWindowTpsLimitStrategyImpl)
return &ThreadSafeFixedWindowTpsLimitStrategyImpl{ return &ThreadSafeFixedWindowTpsLimitStrategyImpl{
fixedWindow: fixedWindowStrategy, fixedWindow: fixedWindowStrategy,
mutex: &sync.Mutex{}, mutex: &sync.Mutex{},
......
...@@ -27,12 +27,13 @@ import ( ...@@ -27,12 +27,13 @@ import (
) )
func TestThreadSafeFixedWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) { func TestThreadSafeFixedWindowTpsLimitStrategyImpl_IsAllowable(t *testing.T) {
strategy := NewThreadSafeFixedWindowTpsLimitStrategyImpl(2, 60000) creator := &threadSafeFixedWindowStrategyCreator{}
strategy := creator.Create(2, 60000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
strategy = NewThreadSafeFixedWindowTpsLimitStrategyImpl(2, 2000) strategy = creator.Create(2, 2000)
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable())
assert.False(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable())
......
...@@ -148,7 +148,7 @@ func (limiter MethodServiceTpsLimiterImpl) IsAllowable(url common.URL, invocatio ...@@ -148,7 +148,7 @@ func (limiter MethodServiceTpsLimiterImpl) IsAllowable(url common.URL, invocatio
limitStrategyConfig := url.GetParam(methodConfigPrefix+constant.TPS_LIMIT_STRATEGY_KEY, limitStrategyConfig := url.GetParam(methodConfigPrefix+constant.TPS_LIMIT_STRATEGY_KEY,
url.GetParam(constant.TPS_LIMIT_STRATEGY_KEY, constant.DEFAULT_KEY)) url.GetParam(constant.TPS_LIMIT_STRATEGY_KEY, constant.DEFAULT_KEY))
limitStateCreator := extension.GetTpsLimitStrategyCreator(limitStrategyConfig) limitStateCreator := extension.GetTpsLimitStrategyCreator(limitStrategyConfig)
limitState, _ = limiter.tpsState.LoadOrStore(limitTarget, limitStateCreator(int(limitRate), int(limitInterval))) limitState, _ = limiter.tpsState.LoadOrStore(limitTarget, limitStateCreator.Create(int(limitRate), int(limitInterval)))
return limitState.(tps.TpsLimitStrategy).IsAllowable() return limitState.(tps.TpsLimitStrategy).IsAllowable()
} }
......
...@@ -48,10 +48,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Only_Service_Level(t *testing.T ...@@ -48,10 +48,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Only_Service_Level(t *testing.T
mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl := NewMockTpsLimitStrategy(ctrl)
mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1)
extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy {
assert.Equal(t, 20, rate) extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{
assert.Equal(t, 60000, interval) rate: 40,
return mockStrategyImpl interval: 60000,
t: t,
strategy: mockStrategyImpl,
}) })
limiter := GetMethodServiceTpsLimiter() limiter := GetMethodServiceTpsLimiter()
...@@ -95,10 +97,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Method_Level_Override(t *testin ...@@ -95,10 +97,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Method_Level_Override(t *testin
mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl := NewMockTpsLimitStrategy(ctrl)
mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1)
extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy {
assert.Equal(t, 40, rate) extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{
assert.Equal(t, 7000, interval) rate: 40,
return mockStrategyImpl interval: 7000,
t: t,
strategy: mockStrategyImpl,
}) })
limiter := GetMethodServiceTpsLimiter() limiter := GetMethodServiceTpsLimiter()
...@@ -123,13 +127,28 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Both_Method_And_Service(t *test ...@@ -123,13 +127,28 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Both_Method_And_Service(t *test
mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl := NewMockTpsLimitStrategy(ctrl)
mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1)
extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy {
assert.Equal(t, 40, rate) extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{
assert.Equal(t, 3000, interval) rate: 40,
return mockStrategyImpl interval: 3000,
t: t,
strategy: mockStrategyImpl,
}) })
limiter := GetMethodServiceTpsLimiter() limiter := GetMethodServiceTpsLimiter()
result := limiter.IsAllowable(*invokeUrl, invoc) result := limiter.IsAllowable(*invokeUrl, invoc)
assert.True(t, result) assert.True(t, result)
} }
type mockStrategyCreator struct {
rate int
interval int
t *testing.T
strategy tps.TpsLimitStrategy
}
func (creator *mockStrategyCreator) Create(rate int, interval int) tps.TpsLimitStrategy {
assert.Equal(creator.t, creator.rate, rate)
assert.Equal(creator.t, creator.interval, interval)
return creator.strategy
}
...@@ -34,3 +34,7 @@ package tps ...@@ -34,3 +34,7 @@ package tps
type TpsLimitStrategy interface { type TpsLimitStrategy interface {
IsAllowable() bool IsAllowable() bool
} }
type TpsLimitStrategyCreator interface {
Create(rate int, interval int) TpsLimitStrategy
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment