Ограничиваем скорость операций в Golang | OTUS

Курсы

Программирование
PHP Developer. Basic
-50%
Специализация PHP Developer iOS Developer. Professional Golang Developer. Professional Python Developer. Basic iOS Developer. Basic Архитектура и шаблоны проектирования MS SQL Server Developer Highload Architect Специализация C++ Developer Cloud Solution Architecture Специализация Java-разработчик Android Developer. Professional Программист С Специализация Fullstack developer VR/AR - разработчик Microservice Architecture Software Architect Team Lead Web-разработчик на Python Rust Developer NoSQL C# Developer. Professional Разработчик программных роботов (RPA) на базе UiPath и PIX Kotlin Backend Developer React.js Developer Node.js Developer Flutter Mobile Developer Symfony Framework C# Developer. Basic Unreal Engine Game Developer Groovy Developer
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Ограничиваем скорость операций в Golang

GoPro_Headline_970x70-1801-dc9277.png

Для ограничения скорости операций в единицу времени в языке программирования Go можно использовать 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)
  }
}

По материалам блога https://golang-blog.blogspot.com/.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться