- ebai限访问频率按门店来

This commit is contained in:
gazebo
2019-04-10 14:31:38 +08:00
parent df987cd93e
commit 9fd70a7446
4 changed files with 89 additions and 31 deletions

View File

@@ -8,34 +8,82 @@ const (
var ( var (
apiLimitConfigs = map[string]*platformapi.LimiterConfig{ apiLimitConfigs = map[string]*platformapi.LimiterConfig{
allAPI: &platformapi.LimiterConfig{ // allAPI: &platformapi.LimiterConfig{
MaxAccessCount: 5, // MaxAccessCount: 5,
// TimeGapMilliSecond: 1000,
// },
"sku.shop.category.update": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000,
},
"sku.shop.category.delete": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000, TimeGapMilliSecond: 1000,
}, },
"sku.create": &platformapi.LimiterConfig{ "sku.create": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1, MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000, TimeGapMilliSecond: 1000,
}, },
"sku.delete": &platformapi.LimiterConfig{ "sku.online": &platformapi.LimiterConfig{
MaxAccessCount: 1, MaxAccessCount: 1,
TimeGapMilliSecond: 2000, TimeGapMilliSecond: 1000 + 200,
}, },
"sku.shop.category.delete": &platformapi.LimiterConfig{ "sku.online.one": &platformapi.LimiterConfig{
MaxAccessCount: 1, MaxAccessCount: 10 - 1,
TimeGapMilliSecond: 1000, TimeGapMilliSecond: 1000,
}, },
"sku.shop.category.create": &platformapi.LimiterConfig{ "sku.offline": &platformapi.LimiterConfig{
MaxAccessCount: 2, MaxAccessCount: 1,
TimeGapMilliSecond: 1000 + 200,
},
"sku.offline.one": &platformapi.LimiterConfig{
MaxAccessCount: 10 - 1,
TimeGapMilliSecond: 1000,
},
"sku.update": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000, TimeGapMilliSecond: 1000,
}, },
"sku.list": &platformapi.LimiterConfig{ "sku.list": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 3, MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000,
},
"sku.price.update.batch": &platformapi.LimiterConfig{
MaxAccessCount: 1,
TimeGapMilliSecond: 1000 + 200,
},
"sku.stock.update.batch": &platformapi.LimiterConfig{
MaxAccessCount: 2,
TimeGapMilliSecond: 1000 + 200,
},
"sku.delete": &platformapi.LimiterConfig{
MaxAccessCount: 1,
TimeGapMilliSecond: 1000 + 200,
},
"sku.shop.category.create": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000,
},
"sku.shop.category.map": &platformapi.LimiterConfig{
MaxAccessCount: 10 - 1,
TimeGapMilliSecond: 1000,
},
"sku.category.list": &platformapi.LimiterConfig{
MaxAccessCount: 1,
TimeGapMilliSecond: 1000 + 200,
},
"sku.brand.list": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000,
},
"sku.shop.category.get": &platformapi.LimiterConfig{
MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000, TimeGapMilliSecond: 1000,
}, },
} }
defaultAPILimitConfig = &platformapi.LimiterConfig{ // defaultAPILimitConfig = &platformapi.LimiterConfig{
MaxAccessCount: 5 - 2, // MaxAccessCount: 5 - 1,
TimeGapMilliSecond: 1000, // TimeGapMilliSecond: 1000,
} // }
) )

View File

@@ -63,7 +63,7 @@ func New(source, secret string, config ...*platformapi.APIConfig) *API {
secret: secret, secret: secret,
client: &http.Client{Timeout: curConfig.ClientTimeout}, client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig, config: &curConfig,
speedLimiter: platformapi.New(apiLimitConfigs, defaultAPILimitConfig), speedLimiter: platformapi.New(apiLimitConfigs, nil), //defaultAPILimitConfig),
storeCookies: make(map[string]string), storeCookies: make(map[string]string),
} }
return api return api
@@ -96,7 +96,7 @@ func (a *API) getShopID(body map[string]interface{}) (shopID string) {
func (a *API) AccessAPI(cmd string, body map[string]interface{}) (retVal *ResponseResult, err error) { func (a *API) AccessAPI(cmd string, body map[string]interface{}) (retVal *ResponseResult, err error) {
baseapi.SugarLogger.Debugf("ebai AccessAPI cmd:%s", cmd) baseapi.SugarLogger.Debugf("ebai AccessAPI cmd:%s", cmd)
// a.speedLimiter.AccessAPI(allAPI) // a.speedLimiter.AccessAPI(allAPI)
a.speedLimiter.AccessAPI(cmd) a.speedLimiter.AccessAPI(cmd, a.getShopID(body))
if body == nil { if body == nil {
body = make(map[string]interface{}, 0) body = make(map[string]interface{}, 0)
} }

View File

@@ -1,6 +1,7 @@
package platformapi package platformapi
import ( import (
"math"
"sync" "sync"
"time" "time"
@@ -13,36 +14,45 @@ type LimiterConfig struct {
} }
type Limiter struct { type Limiter struct {
limitConfig map[string]*ratelimit.Bucket limitBucketMap map[string]*ratelimit.Bucket
defaultConfig *LimiterConfig limitConfigMap map[string]*LimiterConfig
defaultConfig *LimiterConfig
sync.RWMutex sync.RWMutex
} }
func New(config map[string]*LimiterConfig, defaultConfig ...*LimiterConfig) *Limiter { func New(config map[string]*LimiterConfig, defaultConfig ...*LimiterConfig) *Limiter {
limiter := &Limiter{ limiter := &Limiter{
limitConfig: make(map[string]*ratelimit.Bucket), limitConfigMap: config,
} limitBucketMap: make(map[string]*ratelimit.Bucket),
for k, v := range config {
limiter.limitConfig[k] = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapMilliSecond)*time.Millisecond, int64(v.MaxAccessCount), int64(v.MaxAccessCount))
} }
// for k, v := range config {
// limiter.limitBucketMap[k] = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapMilliSecond)*time.Millisecond, int64(v.MaxAccessCount), int64(v.MaxAccessCount))
// }
if len(defaultConfig) > 0 { if len(defaultConfig) > 0 {
limiter.defaultConfig = defaultConfig[0] limiter.defaultConfig = defaultConfig[0]
} }
return limiter return limiter
} }
func (l *Limiter) AccessAPI(apiName string) { func (l *Limiter) AccessAPI(apiName, shopID string) {
bucketKey := shopID + "." + apiName
l.RLock() l.RLock()
bucket := l.limitConfig[apiName] bucket := l.limitBucketMap[bucketKey]
l.RUnlock() l.RUnlock()
if bucket == nil && l.defaultConfig != nil { if bucket == nil {
l.Lock() l.Lock()
if bucket = l.limitConfig[apiName]; bucket == nil { if bucket = l.limitBucketMap[bucketKey]; bucket == nil {
if v := l.defaultConfig; v != nil { v := l.limitConfigMap[apiName]
bucket = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapMilliSecond)*time.Millisecond, int64(v.MaxAccessCount), int64(v.MaxAccessCount)) if v == nil {
l.limitConfig[apiName] = bucket v = l.defaultConfig
} }
if v != nil {
bucket = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapMilliSecond)*time.Millisecond, int64(v.MaxAccessCount), int64(v.MaxAccessCount))
} else {
bucket = ratelimit.NewBucket(time.Second, math.MaxInt64) // 占位用
}
l.limitBucketMap[bucketKey] = bucket
} }
l.Unlock() l.Unlock()
} }

View File

@@ -26,7 +26,7 @@ func TestLimitSpeed(t *testing.T) {
utils.CallFuncAsync(func() { utils.CallFuncAsync(func() {
count := 0 count := 0
for { for {
limiter.AccessAPI("limited1persecond") limiter.AccessAPI("limited1persecond", "")
fmt.Printf("limited1persecond, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count) fmt.Printf("limited1persecond, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count)
count++ count++
} }
@@ -34,7 +34,7 @@ func TestLimitSpeed(t *testing.T) {
utils.CallFuncAsync(func() { utils.CallFuncAsync(func() {
count := 0 count := 0
for { for {
limiter.AccessAPI("limited10per10second") limiter.AccessAPI("limited10per10second", "")
fmt.Printf("limited10per10second, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count) fmt.Printf("limited10per10second, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count)
count++ count++
} }
@@ -42,7 +42,7 @@ func TestLimitSpeed(t *testing.T) {
utils.CallFuncAsync(func() { utils.CallFuncAsync(func() {
count := 0 count := 0
for { for {
limiter.AccessAPI("otherAPI") limiter.AccessAPI("otherAPI", "")
fmt.Printf("otherAPI, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count) fmt.Printf("otherAPI, time:%s, count:%d\n", time.Now().Format("2006-01-02 15:04:05.00000"), count)
count++ count++
} }