如何设计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
}
刚开始了解 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
}