如何设计goroutines程序来处理api限制错误

How to design goroutines program to handle api limit error

刚开始了解 goroutines 的强大功能。

我有大约 100 个帐户和大约 10 个区域,循环遍历它们以使用 golang 创建大约 1000 个 goroutines 以提高阅读速度。它工作得太快以至于达到了 API return 20/秒的限制。

如何保证所有的goroutines都能保持在最大调用率(20/s)?我不确定哪种 golang 并发方法最适合一起处理错误。

例如:

func readInstance(acc string, region string, wg *sync.WaitGroup) {
    defer wg.Done()
    response, err := client.DescribeInstances(acc, region)
    if err != nil {
        log.Println(err) // API limit exceeding 20
        return
    }
    .
    .
    .
    .

}

func main() {
    accounts := []string{"g", "h", "i", ...}
    regions := []string{"g", "h", "i", ...}
    for _, region := range regions {
        for i := 0; i < len(accounts); i++ {
            wg.Add(1)
            go readInstance(accounts[i], region, &wg)
        }
    }
    wg.Wait()
}

如果您对在特定时间内可以执行的请求数量有固定的上限,则可以使用 time.NewTicker() 来 space 解决问题。

c := time.NewTicker(50 * time.Millisecond)
defer c.Stop()

现在,当您要发出服务器请求时,只需插入

<- c.C

在实际请求之前。

我想你可以试试这个:https://github.com/uber-go/ratelimit

根据文档,它是并发安全的。

import (
    "fmt"
    "time"

    "go.uber.org/ratelimit"
)

func main() {
    rl := ratelimit.New(100) // per second

    prev := time.Now()
    for i := 0; i < 10; i++ {
        now := rl.Take()
        fmt.Println(i, now.Sub(prev))
        prev = now
    }

    // Output:
    // 0 0
    // 1 10ms
    // 2 10ms
    // 3 10ms
    // 4 10ms
    // 5 10ms
    // 6 10ms
    // 7 10ms
    // 8 10ms
    // 9 10ms
}