我一直在試圖爲我的應用程序做一個速率限制器,並且遇到了這個代碼。閱讀完它後,我仍然無法理解它究竟發生了什麼。麻煩了解這個速率限制器如何工作
我目前的理解:
1)SetSmallRateLimit和SetLongRateLimit被調用初始化通道和開始運行的夠程的處理器。
2)當調用requestAndUnmarshal時,checkRateLimiter發送一個信號給隊列通道。
我不明白:
1)RateLimitHandler睡time.After(pertime)的持續時間,之後清除隊列通道。不確定triggerWatcher和returnChan在做什麼。
2)checkTimeTrigger - 不明白這個函數正在做什麼或它的目的。
var (
smallRateChan rateChan
longRateChan rateChan
)
type rateChan struct {
RateQueue chan bool
TriggerChan chan bool
}
//10 requests every 10 seconds
func SetSmallRateLimit(numrequests int, pertime time.Duration) {
smallRateChan = rateChan{
RateQueue: make(chan bool, numrequests),
TriggerChan: make(chan bool),
}
go rateLimitHandler(smallRateChan, pertime)
}
//500 requests every 10 minutes
func SetLongRateLimit(numrequests int, pertime time.Duration) {
longRateChan = rateChan{
RateQueue: make(chan bool, numrequests),
TriggerChan: make(chan bool),
}
go rateLimitHandler(longRateChan, pertime)
}
func rateLimitHandler(RateChan rateChan, pertime time.Duration) {
returnChan := make(chan bool)
go timeTriggerWatcher(RateChan.TriggerChan, returnChan)
for {
<-returnChan
<-time.After(pertime)
go timeTriggerWatcher(RateChan.TriggerChan, returnChan)
length := len(RateChan.RateQueue)
for i := 0; i < length; i++ {
<-RateChan.RateQueue
}
}
}
func timeTriggerWatcher(timeTrigger chan bool, returnChan chan bool) {
timeTrigger <- true
returnChan <- true
}
func requestAndUnmarshal(requestURL string, v interface{}) (err error) {
checkRateLimiter(smallRateChan)
checkRateLimiter(longRateChan)
resp, err := http.Get(requestURL)
defer resp.Body.Close()
if err != nil {
return
}
checkTimeTrigger(smallRateChan)
checkTimeTrigger(longRateChan)
if resp.StatusCode != http.StatusOK {
return RiotError{StatusCode: resp.StatusCode}
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
err = json.Unmarshal(body, v)
if err != nil {
return
}
return
}
func checkRateLimiter(RateChan rateChan) {
if RateChan.RateQueue != nil && RateChan.TriggerChan != nil {
RateChan.RateQueue <- true
}
}
func checkTimeTrigger(RateChan rateChan) {
if RateChan.RateQueue != nil && RateChan.TriggerChan != nil {
select {
case <-RateChan.TriggerChan:
default:
}
}
}
具有「突發」速率和「長期穩態」速率通常很有用。不一定與您提供的比率(90 000個請求/秒作爲突發速率,0.00028個請求/秒用於穩定狀態)。如果你的值更合理(穩態1請求/秒,突發速率5請求/秒;比方說),這是一個有用的速率限制方法。 – Vatine