Чтобы ограничить скорость операций в единицу времени, используйте time.Ticker. Это хорошо работает для скоростей до десятков операций в секунду. Для более высоких скоростей выберите ограничитель скорости сегмента токенов, такой как Limiter из golang.org/x/time/rate.
import "time"
const rateLimit = time.Second / 10 // 10 calls per second
// Client это интерфейс,
// который вызывает что-то с полезной нагрузкой.
type Client interface {
Call(*Payload)
}
// Payload это некоторая полезная нагрузка,
// которую Client отправляет при вызове.
type Payload struct {}
// RateLimitCall ограничивает скорость клиентских вызовов полезной нагрузки.
func RateLimitCall(client Client, payloads []*Payload) {
throttle := time.Tick(rateLimit)
for _, payload := range payloads {
<-throttle // ограничение скорости клиентских вызовов
go client.Call(payload)
}
}
Чтобы разрешить некоторые всплески, добавьте к дросселю буфер:
import "time"
const rateLimit = time.Second / 10 // 10 calls per second
// Client это интерфейс,
// который вызывает что-то с полезной нагрузкой.
type Client interface {
Call(*Payload)
}
// Payload это некоторая полезная нагрузка,
// которую Client отправляет при вызове.
type Payload struct {}
// BurstRateLimitCall позволяет ограничивать
// пакетную скорость клиентских вызовов полезной нагрузки.
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 // выходим из горутины, когда окружающая функция завершается
}
}
}()
for _, payload := range payloads {
<-throttle // ограничение скорости клиентских вызовов
go client.Call(payload)
}
}
Читайте также:
Комментариев нет:
Отправить комментарий