所以我正在编写一个实用程序来查询工作中的 API,它们每 10 秒限制为 20 次调用。很简单,我只会将我的通话限制在自上次通话以来至少过去 0.5 秒。在我尝试使用 goroutines 之前,我的 Throttle 实用程序运行良好。现在我正在使用结构/方法组合:func (c *CTKAPI) Throttle() {if c.Debug{fmt.Println("\t\t\tEntering Throttle()")}for { //in case something else makes a call while we're sleeping, we need to re-check if t := time.Now().Sub(c.LastCallTime); t < c.ThrottleTime { if c.Debug{fmt.Printf("\t\t\tThrottle: Sleeping %v\n", c.ThrottleTime - t)} time.Sleep(c.ThrottleTime - t) } else { if c.Debug{fmt.Println("\t\t\tThrottle: Released.")} break }}c.LastCallTime = time.Now()if c.Debug{fmt.Println("\t\t\tExiting Throttle()")}}然后我在每个 goroutine 中的每次调用之前调用 what.Throttle() 以确保在启动下一个调用之前我已经等待了至少半秒。但这似乎不可靠并且会产生不可预测的结果。有没有更优雅的方式来限制并发请求?-麦克风
3 回答
偶然的你
TA贡献1841条经验 获得超3个赞
实际上有一个更简单的方法来做到这一点:创建一个时间行情。
package main
import (
"fmt"
"sync"
"time"
)
func main() {
rateLimit := time.Tick(500 * time.Millisecond)
<-rateLimit
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
<-rateLimit
fmt.Println("Hello", i)
wg.Done()
}(i)
}
wg.Wait()
}
慕尼黑8549860
TA贡献1818条经验 获得超11个赞
因为您正在引入数据竞争,所以多个例程正在访问/更改 c.LastCallTime。
您可以time.Tick
改用或制作c.LastCallTime
一个int64
( c.LastCallTime = time.Now().Unix()
) 并用于atomic.LoadInt64/StoreInt64
检查它。
- 3 回答
- 0 关注
- 167 浏览
添加回答
举报
0/150
提交
取消