From 6a5afbb07f8a51c1f62a74eebe0c9395c8e2236f Mon Sep 17 00:00:00 2001 From: gazebo Date: Sat, 27 Oct 2018 12:29:27 +0800 Subject: [PATCH] - default config support for limt_access_speed. * fix bug when request.Body is nil. --- platformapi/ebaiapi/access_limit.go | 7 ++++++- platformapi/ebaiapi/ebaiapi.go | 2 +- platformapi/limit_access_speed.go | 22 ++++++++++++++++++++-- platformapi/limit_access_speed_test.go | 11 +++++++++++ platformapi/platformapi.go | 4 +++- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/platformapi/ebaiapi/access_limit.go b/platformapi/ebaiapi/access_limit.go index d307c55a..bee5c991 100644 --- a/platformapi/ebaiapi/access_limit.go +++ b/platformapi/ebaiapi/access_limit.go @@ -3,7 +3,7 @@ package ebaiapi import "git.rosy.net.cn/baseapi/platformapi" var ( - apiLimitConfig = map[string]*platformapi.LimiterConfig{ + apiLimitConfigs = map[string]*platformapi.LimiterConfig{ "sku.create": &platformapi.LimiterConfig{ MaxAccessCount: 5 - 1, TimeGapInSecond: 1, @@ -21,4 +21,9 @@ var ( TimeGapInSecond: 1, }, } + + defaultAPILimitConfig = &platformapi.LimiterConfig{ + MaxAccessCount: 5 - 2, + TimeGapInSecond: 1, + } ) diff --git a/platformapi/ebaiapi/ebaiapi.go b/platformapi/ebaiapi/ebaiapi.go index d69f43f3..9c86fba1 100644 --- a/platformapi/ebaiapi/ebaiapi.go +++ b/platformapi/ebaiapi/ebaiapi.go @@ -52,7 +52,7 @@ func New(source, secret string, config ...*platformapi.APIConfig) *API { secret: secret, client: &http.Client{Timeout: curConfig.ClientTimeout}, config: &curConfig, - speedLimiter: platformapi.New(apiLimitConfig), + speedLimiter: platformapi.New(apiLimitConfigs, defaultAPILimitConfig), } return api } diff --git a/platformapi/limit_access_speed.go b/platformapi/limit_access_speed.go index 74501c22..ea8a335f 100644 --- a/platformapi/limit_access_speed.go +++ b/platformapi/limit_access_speed.go @@ -1,6 +1,7 @@ package platformapi import ( + "sync" "time" "github.com/juju/ratelimit" @@ -12,21 +13,38 @@ type LimiterConfig struct { } type Limiter struct { - limitConfig map[string]*ratelimit.Bucket + limitConfig map[string]*ratelimit.Bucket + defaultConfig *LimiterConfig + sync.RWMutex } -func New(config map[string]*LimiterConfig) *Limiter { +func New(config map[string]*LimiterConfig, defaultConfig ...*LimiterConfig) *Limiter { limiter := &Limiter{ limitConfig: make(map[string]*ratelimit.Bucket), } for k, v := range config { limiter.limitConfig[k] = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapInSecond)*time.Second, int64(v.MaxAccessCount), int64(v.MaxAccessCount)) } + if len(defaultConfig) > 0 { + limiter.defaultConfig = defaultConfig[0] + } return limiter } func (l *Limiter) AccessAPI(apiName string) { + l.RLock() bucket := l.limitConfig[apiName] + l.RUnlock() + + if bucket == nil && l.defaultConfig != nil { + l.Lock() + if bucket = l.limitConfig[apiName]; bucket == nil { + v := l.defaultConfig + bucket = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapInSecond)*time.Second, int64(v.MaxAccessCount), int64(v.MaxAccessCount)) + l.limitConfig[apiName] = bucket + } + l.Unlock() + } if bucket != nil { bucket.Wait(1) } diff --git a/platformapi/limit_access_speed_test.go b/platformapi/limit_access_speed_test.go index 2909d66b..f34060d2 100644 --- a/platformapi/limit_access_speed_test.go +++ b/platformapi/limit_access_speed_test.go @@ -18,6 +18,9 @@ func TestLimitSpeed(t *testing.T) { MaxAccessCount: 10, TimeGapInSecond: 10, }, + }, &LimiterConfig{ + MaxAccessCount: 1, + TimeGapInSecond: 2, }) go func() { @@ -36,5 +39,13 @@ func TestLimitSpeed(t *testing.T) { count++ } }() + go func() { + count := 0 + for { + limiter.AccessAPI("otherAPI") + fmt.Printf("otherAPI, time:%s, count:%d\n", utils.GetCurTimeStr(), count) + count++ + } + }() time.Sleep(30 * time.Second) } diff --git a/platformapi/platformapi.go b/platformapi/platformapi.go index 86f8994e..4325d59e 100644 --- a/platformapi/platformapi.go +++ b/platformapi/platformapi.go @@ -85,7 +85,9 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http. for { savedBuf := new(bytes.Buffer) request := handleRequest() - request.Body = ioutil.NopCloser(io.TeeReader(request.Body, savedBuf)) + if request.Body != nil { + request.Body = ioutil.NopCloser(io.TeeReader(request.Body, savedBuf)) + } response, err := client.Do(request) if err != nil { baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err)