- default config support for limt_access_speed.
* fix bug when request.Body is nil.
This commit is contained in:
@@ -3,7 +3,7 @@ package ebaiapi
|
|||||||
import "git.rosy.net.cn/baseapi/platformapi"
|
import "git.rosy.net.cn/baseapi/platformapi"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
apiLimitConfig = map[string]*platformapi.LimiterConfig{
|
apiLimitConfigs = map[string]*platformapi.LimiterConfig{
|
||||||
"sku.create": &platformapi.LimiterConfig{
|
"sku.create": &platformapi.LimiterConfig{
|
||||||
MaxAccessCount: 5 - 1,
|
MaxAccessCount: 5 - 1,
|
||||||
TimeGapInSecond: 1,
|
TimeGapInSecond: 1,
|
||||||
@@ -21,4 +21,9 @@ var (
|
|||||||
TimeGapInSecond: 1,
|
TimeGapInSecond: 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultAPILimitConfig = &platformapi.LimiterConfig{
|
||||||
|
MaxAccessCount: 5 - 2,
|
||||||
|
TimeGapInSecond: 1,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -52,7 +52,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(apiLimitConfig),
|
speedLimiter: platformapi.New(apiLimitConfigs, defaultAPILimitConfig),
|
||||||
}
|
}
|
||||||
return api
|
return api
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package platformapi
|
package platformapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juju/ratelimit"
|
"github.com/juju/ratelimit"
|
||||||
@@ -12,21 +13,38 @@ type LimiterConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Limiter 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{
|
limiter := &Limiter{
|
||||||
limitConfig: make(map[string]*ratelimit.Bucket),
|
limitConfig: make(map[string]*ratelimit.Bucket),
|
||||||
}
|
}
|
||||||
for k, v := range config {
|
for k, v := range config {
|
||||||
limiter.limitConfig[k] = ratelimit.NewBucketWithQuantum(time.Duration(v.TimeGapInSecond)*time.Second, int64(v.MaxAccessCount), int64(v.MaxAccessCount))
|
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
|
return limiter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) AccessAPI(apiName string) {
|
func (l *Limiter) AccessAPI(apiName string) {
|
||||||
|
l.RLock()
|
||||||
bucket := l.limitConfig[apiName]
|
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 {
|
if bucket != nil {
|
||||||
bucket.Wait(1)
|
bucket.Wait(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ func TestLimitSpeed(t *testing.T) {
|
|||||||
MaxAccessCount: 10,
|
MaxAccessCount: 10,
|
||||||
TimeGapInSecond: 10,
|
TimeGapInSecond: 10,
|
||||||
},
|
},
|
||||||
|
}, &LimiterConfig{
|
||||||
|
MaxAccessCount: 1,
|
||||||
|
TimeGapInSecond: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -36,5 +39,13 @@ func TestLimitSpeed(t *testing.T) {
|
|||||||
count++
|
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)
|
time.Sleep(30 * time.Second)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,9 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
|||||||
for {
|
for {
|
||||||
savedBuf := new(bytes.Buffer)
|
savedBuf := new(bytes.Buffer)
|
||||||
request := handleRequest()
|
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)
|
response, err := client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err)
|
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry client.Get return err:%v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user