Go Wiki:速率限制

若要限制每單位時間的作業速率,請使用 time.Ticker。這對於每秒數十個作業的速率很有用。對於更高的速率,建議使用令牌桶速率限制器,例如 golang.org/x/time/rate.Limiter(也可以在 pkg.go.dev 中搜尋 速率限制)。

import "time"

const rateLimit = time.Second / 10  // 10 calls per second

// Client is an interface that calls something with a payload.
type Client interface {
  Call(*Payload)
}

// Payload is some payload a Client would send in a call.
type Payload struct {}

// RateLimitCall rate limits client calls with the payloads.
func RateLimitCall(client Client, payloads []*Payload) {
  throttle := time.Tick(rateLimit)

  for _, payload := range payloads {
    <-throttle  // rate limit our client calls
    go client.Call(payload)
  }
}

若要允許一些突發,請在節流閥中新增一個緩衝區

import "time"

const rateLimit = time.Second / 10  // 10 calls per second

// Client is an interface that calls something with a payload.
type Client interface {
  Call(*Payload)
}

// Payload is some payload a Client would send in a call.
type Payload struct {}

// BurstRateLimitCall allows burst rate limiting client calls with the
// payloads.
func BurstRateLimitCall(ctx context.Context, client Client, payloads []*Payload, burstLimit int) {
  throttle := make(chan time.Time, burstLimit)

  ctx, cancel := context.WithCancel(ctx)
  defer cancel()

  go func() {
    ticker := time.NewTicker(rateLimit)
    defer ticker.Stop()
    for t := range ticker.C {
        select {
        case throttle <- t:
        case <-ctx.Done():
            return // exit goroutine when surrounding function returns
        }
    }
  }()

  for _, payload := range payloads {
    <-throttle  // rate limit our client calls
    go client.Call(payload)
  }
}

此內容是 Go Wiki 的一部分。