【问题标题】:Worker pool implementation to limit http requests per second工作池实现以限制每秒的 http 请求
【发布时间】:2020-06-03 02:17:45
【问题描述】:

我是 Go 语言的新手,正在尝试实现受限的 GCP API 调用。即限制我的应用每秒调用 API 的次数,因此 Google 不会阻止我。

我一直在关注工作池模式,例如 here

与链接示例类似的设计将是:

  • 使两个通道(作业、结果)的容量与要进行的 API 调用总数相同
  • 创建一个特定大小的工作人员池(比如 10 个工作人员)
  • 每个工作人员在进行 API 调用时通过作业通道,并将响应存储到结果通道中,等待时间为 1 秒

我的问题是:

  • 我是否理解正确,10 名工作人员每人有 1 秒的等待期意味着我的应用每秒进行大约 10 次 API 调用?
  • 这 10 名工作人员如何相互通信,以免他们踩到对方的脚趾,即两个工作人员不查询相同的 GCS 路径。

当然还有一个终极问题:使用工作池是不是有点矫枉过正?

谢谢!

【问题讨论】:

  • 如果您可以使用单个 goroutine 突破 API 速率限制,那么使用工作池是没有意义的。 API 速率限制是多少?执行请求的时间是什么时候?如果您确实需要限制速率,请参阅godoc.org/golang.org/x/time/rate
  • @CeriseLimón,感谢您的链接!它正在获得 GCS 中对象的大小,其中可能有数万个。根据cloud.google.com/storage/docs/request-rate,我看到每秒 5K 的速率限制
  • 那篇文章没有说明有速率限制。它说“对于几周内没有高请求率或具有新的对象键范围的任何存储桶,您应该逐渐提高请求率”和“如果您的请求率预计会超过这些阈值,您应该从低于或接近阈值的请求率开始,然后将请求率提高一倍,不超过每 20 分钟。”由于您要为每个请求付费,因此硬性速率限制会很奇怪。
  • @Peter,当我开始使用没有任何速率限制的应用程序时,我收到诸如“dial tcp lookup storage.googleapis.com no such host”之类的错误,谷歌搜索似乎建议我我受到 GCP 的限制。没有?
  • 没有。您的 DNS 服务器无法访问或出现故障或类似情况。

标签: go worker-pool


【解决方案1】:

也许您可以使用 Sync.Mutex 和 time.After 实现一个 Throttler,如下所示

package main

import (
    "fmt"
    "os"
    "os/signal"
    "sync"
    "syscall"
    "time"
)

type Throttler struct {
    invocations int
    duration time.Duration
    m sync.Mutex
    max int
}

func (t *Throttler) Throttle() {
    t.m.Lock()
    defer t.m.Unlock()
    t.invocations += 1
    if t.invocations >= t.max {
        <-time.After(t.duration) // This block until the time period expires
        t.invocations = 0
    }
}

func main() {
    t := &Throttler{
        max: 2,
        duration: time.Second,
    }
    // Launch your workers passing in the throttler created above.
    for i := 0; i < 10; i++ {
        fmt.Println("starting worker")
        go Worker(t);
    }

    // This just to prevent the main from exiting.
    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c // This will block until you manually exists with CRl-C
}

// worker
func Worker(t *Throttler)  {
    t.Throttle()
    fmt.Println("Work done!!")
}

【讨论】:

  • 感谢您的解决方案。我在这个问题上的解决方案似乎有效,所以我现在会坚持下去。 (我没有投反对票……)
  • 哦,不用担心投反对票。我只是对您的问题感到好奇,并认为这是实现节流器的一种方法。
猜你喜欢
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 2018-07-16
  • 2021-11-18
相关资源
最近更新 更多