go - 无法理解此速率限制器的工作原理

标签 go

我一直在尝试为我的应用程序制作一个速率限制器并遇到了这段代码。读完之后,我仍然无法理解它到底做了什么。

我目前的理解:

1) 调用 SetSmallRateLimit 和 SetLongRateLimit 来初始化 channel 并开始在 goroutine 中运行处理程序。

2)调用requestAndUnmarshal时,checkRateLimiter向队列 channel 发送信号。

我不明白的地方:

1) RateLimitHandler 休眠持续时间.After(pertime) 之后清除队列 channel 。不确定 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:
        }
    }
}

最佳答案

我认为您不应该使用此代码来学习任何有用的东西。 我不确定 但它似乎试图限制请求率但这是错误的。它允许发出一定数量的请求,然后等待一个时间间隔。在时间间隔之后,它允许您再次发出请求。所有这些都是以非常复杂的方式完成的。

但这会导致非常奇怪的场景。假设您制作 1req/h,您的限制是 500req/20sec。然后这段代码会让你在 500 小时后等待 20 秒并允许再次发出请求。

checkTimeTrigger 从 RateChan.TriggerChan 中删除一条消息(如果有的话),如果没有则什么都不做并立即返回。

这段代码显然不是DRY .更好用https://godoc.org/golang.org/x/time/rate你想限制你的请求率吗?

关于go - 无法理解此速率限制器的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34652057/

相关文章:

go - Golang-创建与传递的类型相同的对象

go - 从函数返回时无法接收到正确的对象

Golang cookie 的时间戳为空

go - 如何在 go 中获取指向类型化函数的函数指针?

loops - "Infinite loop"导致无法访问的代码

go - 为什么所有的 goroutines 都在 sleep - 僵局。识别瓶颈

go - 如何为指向不同结构的指针实现相同的功能?

methods - 带有方法/函数的 Golang 逗号

go - 模拟 Go 数据库 SDK

git - 使用 git 设置正确的 Golang 目录结构以在自定义包上使用 go build