diff --git a/common/extension/tps_limit.go b/common/extension/tps_limit.go index 65891c79336224f59b66f8312693c6b5151a7e28..151c33ad5e64ffa4059489e2cbcfae6f2e823328 100644 --- a/common/extension/tps_limit.go +++ b/common/extension/tps_limit.go @@ -22,7 +22,7 @@ import ( ) 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) ) @@ -39,11 +39,11 @@ func GetTpsLimiter(name string) tps.TpsLimiter { return creator() } -func SetTpsLimitStrategy(name string, creator func(rate int, interval int) tps.TpsLimitStrategy) { +func SetTpsLimitStrategy(name string, creator tps.TpsLimitStrategyCreator) { tpsLimitStrategy[name] = creator } -func GetTpsLimitStrategyCreator(name string) func(rate int, interval int) tps.TpsLimitStrategy { +func GetTpsLimitStrategyCreator(name string) tps.TpsLimitStrategyCreator { creator, ok := tpsLimitStrategy[name] if !ok { panic("TpsLimitStrategy for " + name + " is not existing, make sure you have import the package " + diff --git a/filter/impl/tps/impl/tps_limit_fix_window_strategy.go b/filter/impl/tps/impl/tps_limit_fix_window_strategy.go index 8805dbd2744df658c85066353fc431631994bd03..285ecfa658cf838cc1140ba716bd72e1976b86fe 100644 --- a/filter/impl/tps/impl/tps_limit_fix_window_strategy.go +++ b/filter/impl/tps/impl/tps_limit_fix_window_strategy.go @@ -33,8 +33,9 @@ const ( ) func init() { - extension.SetTpsLimitStrategy(FixedWindowKey, NewFixedWindowTpsLimitStrategyImpl) - extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, NewFixedWindowTpsLimitStrategyImpl) + creator := &fixedWindowStrategyCreator{} + extension.SetTpsLimitStrategy(FixedWindowKey, creator) + extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, creator) } /** @@ -76,7 +77,9 @@ func (impl *FixedWindowTpsLimitStrategyImpl) IsAllowable() bool { 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{ rate: int32(rate), interval: int64(interval) * int64(time.Millisecond), // convert to ns diff --git a/filter/impl/tps/impl/tps_limit_fix_window_strategy_test.go b/filter/impl/tps/impl/tps_limit_fix_window_strategy_test.go index 4cf52b29267e7e2ec58f4fe8e68b657ffc9dbef4..7ef539ed3b2b93da5c56a05f606e75282226d1ef 100644 --- a/filter/impl/tps/impl/tps_limit_fix_window_strategy_test.go +++ b/filter/impl/tps/impl/tps_limit_fix_window_strategy_test.go @@ -27,12 +27,13 @@ import ( ) 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.False(t, strategy.IsAllowable()) - strategy = NewFixedWindowTpsLimitStrategyImpl(2, 2000) + strategy = creator.Create(2, 2000) assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable()) diff --git a/filter/impl/tps/impl/tps_limit_sliding_window_strategy.go b/filter/impl/tps/impl/tps_limit_sliding_window_strategy.go index c48c818f5e2674ce4d1b34bc4b6c5d0e42f8430d..d1a5db6e259ffa63282065f881f6cc8360c8d25b 100644 --- a/filter/impl/tps/impl/tps_limit_sliding_window_strategy.go +++ b/filter/impl/tps/impl/tps_limit_sliding_window_strategy.go @@ -29,7 +29,7 @@ import ( ) func init() { - extension.SetTpsLimitStrategy("slidingWindow", NewSlidingWindowTpsLimitStrategyImpl) + extension.SetTpsLimitStrategy("slidingWindow", &slidingWindowStrategyCreator{}) } /** @@ -80,7 +80,9 @@ func (impl *SlidingWindowTpsLimitStrategyImpl) IsAllowable() bool { 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{ rate: rate, interval: int64(interval) * int64(time.Millisecond), diff --git a/filter/impl/tps/impl/tps_limit_sliding_window_strategy_test.go b/filter/impl/tps/impl/tps_limit_sliding_window_strategy_test.go index 0169404caba3a9f414e34983ebdd1c0926291a29..075f1d9d2be2d18edfee7dc8691b71da65f5da45 100644 --- a/filter/impl/tps/impl/tps_limit_sliding_window_strategy_test.go +++ b/filter/impl/tps/impl/tps_limit_sliding_window_strategy_test.go @@ -27,14 +27,15 @@ import ( ) 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.False(t, strategy.IsAllowable()) time.Sleep(2100 * time.Millisecond) 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.False(t, strategy.IsAllowable()) diff --git a/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy.go b/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy.go index 5f43e8c3bf6c1db268282a0fb5d9ecc55fb357df..9a1b21a3349845e32cb0fe38b07a7f932ec4f454 100644 --- a/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy.go +++ b/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy.go @@ -27,7 +27,9 @@ import ( ) func init() { - extension.SetTpsLimitStrategy("threadSafeFixedWindow", NewThreadSafeFixedWindowTpsLimitStrategyImpl) + extension.SetTpsLimitStrategy("threadSafeFixedWindow", &threadSafeFixedWindowStrategyCreator{ + fixedWindowStrategyCreator: &fixedWindowStrategyCreator{}, + }) } /** @@ -56,8 +58,12 @@ func (impl *ThreadSafeFixedWindowTpsLimitStrategyImpl) IsAllowable() bool { return impl.fixedWindow.IsAllowable() } -func NewThreadSafeFixedWindowTpsLimitStrategyImpl(rate int, interval int) tps.TpsLimitStrategy { - fixedWindowStrategy := NewFixedWindowTpsLimitStrategyImpl(rate, interval).(*FixedWindowTpsLimitStrategyImpl) +type threadSafeFixedWindowStrategyCreator struct { + fixedWindowStrategyCreator *fixedWindowStrategyCreator +} + +func (creator *threadSafeFixedWindowStrategyCreator) Create(rate int, interval int) tps.TpsLimitStrategy { + fixedWindowStrategy := creator.fixedWindowStrategyCreator.Create(rate, interval).(*FixedWindowTpsLimitStrategyImpl) return &ThreadSafeFixedWindowTpsLimitStrategyImpl{ fixedWindow: fixedWindowStrategy, mutex: &sync.Mutex{}, diff --git a/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy_test.go b/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy_test.go index e05ad4f94fa7ac925fe1e61d14bd9b18b9f561f7..129493962403e0028b09f9646054fda236c99ff7 100644 --- a/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy_test.go +++ b/filter/impl/tps/impl/tps_limit_thread_safe_fix_window_strategy_test.go @@ -27,12 +27,13 @@ import ( ) 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.False(t, strategy.IsAllowable()) - strategy = NewThreadSafeFixedWindowTpsLimitStrategyImpl(2, 2000) + strategy = creator.Create(2, 2000) assert.True(t, strategy.IsAllowable()) assert.True(t, strategy.IsAllowable()) assert.False(t, strategy.IsAllowable()) diff --git a/filter/impl/tps/impl/tps_limiter_method_service.go b/filter/impl/tps/impl/tps_limiter_method_service.go index 3faf0d6e672315bb83e951be45a7f93c4ac508ef..426ae5994867c5a09653641870ebcef531c0d43c 100644 --- a/filter/impl/tps/impl/tps_limiter_method_service.go +++ b/filter/impl/tps/impl/tps_limiter_method_service.go @@ -148,7 +148,7 @@ func (limiter MethodServiceTpsLimiterImpl) IsAllowable(url common.URL, invocatio limitStrategyConfig := url.GetParam(methodConfigPrefix+constant.TPS_LIMIT_STRATEGY_KEY, url.GetParam(constant.TPS_LIMIT_STRATEGY_KEY, constant.DEFAULT_KEY)) 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() } diff --git a/filter/impl/tps/impl/tps_limiter_method_service_test.go b/filter/impl/tps/impl/tps_limiter_method_service_test.go index 006e9463871061488f696366d251c54fb8cefef5..a21d3428398355e92b304c12d27637f00a3730f7 100644 --- a/filter/impl/tps/impl/tps_limiter_method_service_test.go +++ b/filter/impl/tps/impl/tps_limiter_method_service_test.go @@ -48,10 +48,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Only_Service_Level(t *testing.T mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) - extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy { - assert.Equal(t, 20, rate) - assert.Equal(t, 60000, interval) - return mockStrategyImpl + + extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{ + rate: 40, + interval: 60000, + t: t, + strategy: mockStrategyImpl, }) limiter := GetMethodServiceTpsLimiter() @@ -95,10 +97,12 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Method_Level_Override(t *testin mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) - extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy { - assert.Equal(t, 40, rate) - assert.Equal(t, 7000, interval) - return mockStrategyImpl + + extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{ + rate: 40, + interval: 7000, + t: t, + strategy: mockStrategyImpl, }) limiter := GetMethodServiceTpsLimiter() @@ -123,13 +127,28 @@ func TestMethodServiceTpsLimiterImpl_IsAllowable_Both_Method_And_Service(t *test mockStrategyImpl := NewMockTpsLimitStrategy(ctrl) mockStrategyImpl.EXPECT().IsAllowable().Return(true).Times(1) - extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, func(rate int, interval int) tps.TpsLimitStrategy { - assert.Equal(t, 40, rate) - assert.Equal(t, 3000, interval) - return mockStrategyImpl + + extension.SetTpsLimitStrategy(constant.DEFAULT_KEY, &mockStrategyCreator{ + rate: 40, + interval: 3000, + t: t, + strategy: mockStrategyImpl, }) limiter := GetMethodServiceTpsLimiter() result := limiter.IsAllowable(*invokeUrl, invoc) 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 +} diff --git a/filter/impl/tps/tps_limit_strategy.go b/filter/impl/tps/tps_limit_strategy.go index d1af85b464ca3cbb500100b895cdc0badff24898..c55f008a09b3743f728ab0506c6b0095cbfd181c 100644 --- a/filter/impl/tps/tps_limit_strategy.go +++ b/filter/impl/tps/tps_limit_strategy.go @@ -34,3 +34,7 @@ package tps type TpsLimitStrategy interface { IsAllowable() bool } + +type TpsLimitStrategyCreator interface { + Create(rate int, interval int) TpsLimitStrategy +}