每秒运行的goroutine数量是否可以限制?

huangapple go评论204阅读模式
英文:

Is it possible to limit how many goroutines run per second?

问题

我有一个URL列表,我需要使用goroutine并发地发送HTTP请求。有没有办法检查和限制每秒发送的HTTP请求数量?

英文:

I have a list of URLs that I need to use goroutine to fire off HTTP requests concurrently. Is there anyway to check and limit how many of those HTTP requests are sent per second?

答案1

得分: 13

这是一个使用Go语言编写的简单版本,它是Leaky Bucket算法的一种改编,使用了通道和goroutine。在发出请求之前,从rate通道接收一个令牌将检查速率,并在速率限制器为空时阻塞。

  1. // 创建一个带缓冲的通道。
  2. // 通道的容量是最大的突发请求数。
  3. rate := make(chan struct{}, 10)
  4. go func() {
  5. ticker := time.NewTicker(100 * time.Millisecond)
  6. for range ticker.C {
  7. rate <- struct{}{}
  8. }
  9. }()

由于一系列请求的时间超过了平均速率,最终会变成并发请求,因此您可能还需要限制并发性。您可以添加第二个通道作为信号量,在发出请求之前添加一个令牌,并在请求完成后将其删除。

  1. // 将并发限制为5
  2. semaphore := make(chan struct{}, 5)
  3. // 在请求函数中
  4. semaphore <- struct{}{}
  5. defer func() {
  6. <-semaphore
  7. }()

这里有一个稍微完整一些的示例:

https://play.golang.org/p/ZrTPLcdeDF

英文:

A very simple version of this in Go would be an adaptation of a Leaky Bucket algorithm, using a channel and a goroutine. Receiving a token from the rate channel before making a request will check the rate and block if the rate limiter is empty.

  1. // create a buffered channel.
  2. // The capacity of the channel is maximum burst that can be made.
  3. rate := make(chan struct{}, 10)
  4. go func() {
  5. ticker := time.NewTicker(100 * time.Millisecond)
  6. for range ticker.C {
  7. rate &lt;- struct{}{}
  8. }
  9. }()

Since a series of requests that take longer than the average rate will end up being concurrent, you may need to limit concurrency too. You can add a second channel as a semaphore, adding a token to the semaphore before making a request, and removing it when it's complete.

  1. // limit concurrency to 5
  2. semaphore := make(chan struct{}, 5)
  3. // in request function
  4. semaphore &lt;- struct{}{}
  5. defer func() {
  6. &lt;-semaphore
  7. }()

A slightly more complete example is here:

https://play.golang.org/p/ZrTPLcdeDF

答案2

得分: -1

这是一个简单的包,可以帮助你限制同时运行的goroutine数量。请查看https://github.com/zenthangplus/goccm

示例:

  1. package main
  2. import (
  3. "fmt"
  4. "goccm"
  5. "time"
  6. )
  7. func main() {
  8. // 限制同时运行的goroutine数量为3个。
  9. c := goccm.New(3)
  10. for i := 1; i <= 10; i++ {
  11. // 在任何goroutine之前都必须调用此函数
  12. c.Wait()
  13. go func(i int) {
  14. fmt.Printf("Job %d is running\n", i)
  15. time.Sleep(2 * time.Second)
  16. // 当goroutine完成时必须调用此函数
  17. // 或者你可以在goroutine的顶部使用`defer c.Done()`
  18. c.Done()
  19. }(i)
  20. }
  21. // 在关闭主程序后,必须调用此函数以确保所有goroutine都已完成
  22. c.WaitAllDone()
  23. }
英文:

Here is the simple package to help you limit the number of goroutines that are allowed to run concurrently. Please check https://github.com/zenthangplus/goccm

Example:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;goccm&quot;
  5. &quot;time&quot;
  6. )
  7. func main() {
  8. // Limit 3 goroutines to run concurrently.
  9. c := goccm.New(3)
  10. for i := 1; i &lt;= 10; i++ {
  11. // This function have to call before any goroutine
  12. c.Wait()
  13. go func(i int) {
  14. fmt.Printf(&quot;Job %d is running\n&quot;, i)
  15. time.Sleep(2 * time.Second)
  16. // This function have to when a goroutine has finished
  17. // Or you can use `defer c.Done()` at the top of goroutine.
  18. c.Done()
  19. }(i)
  20. }
  21. // This function have to call to ensure all goroutines have finished
  22. // after close the main program.
  23. c.WaitAllDone()
  24. }

huangapple
  • 本文由 发表于 2017年5月5日 01:33:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/43789362.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定