💬 Что из себя представляет паттерн Throttle, применяемый в облачной разработке?
Паттерн
📌 Например:
◆ пользователю может быть разрешено обращаться к сервису не чаще, чем 10 раз в секунду;
◆ клиенту может быть позволено вызывать определенную функцию только один раз в каждые 500 миллисекунд;
◆ учетной записи может быть разрешено только три неудачные попытки входа в систему в течение 24 часов.
Наиболее распространенной причиной применения
📌 Компоненты:
◆
◆
📌 Пример кода:
Паттерн
Throttle
(Дроссельная заслонка) ограничивает частоту вызовов функции некоторым предельным числом вызовов в единицу времени. 📌 Например:
◆ пользователю может быть разрешено обращаться к сервису не чаще, чем 10 раз в секунду;
◆ клиенту может быть позволено вызывать определенную функцию только один раз в каждые 500 миллисекунд;
◆ учетной записи может быть разрешено только три неудачные попытки входа в систему в течение 24 часов.
Наиболее распространенной причиной применения
Throttle
является устранение резких всплесков активности, способных привести к насыщению системы необоснованным количеством дорогостоящих запросов, которые могут привести к ухудшению качества обслуживания и в конечном итоге к отказу. Система может поддерживать автоматическое масштабирование для удовлетворения потребностей пользователей, но на это требуется время, и система может быть не в состоянии реагировать достаточно быстро.📌 Компоненты:
◆
Effector
— функция, частоту вызовов которой нужно ограничить.◆
Throttle
— функция, принимающая Effector
и возвращающая замыкание с той же сигнатурой, что и Effector
.📌 Пример кода:
type Effector func(context.Context) (string, error)
func Throttle(e Effector, max uint, refill uint, d time.Duration) Effector {
var tokens = max
var once sync.Once
return func(ctx context.Context) (string, error) {
if ctx.Err() != nil {
return "", ctx.Err()
}
once.Do(func() {
ticker := time.NewTicker(d)
go func() {
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
t := tokens + refill
if t > max {
t = max
}
tokens = t
}
}
}()
})
if tokens <= 0 {
return "", fmt.Errorf("too many calls")
}
tokens--
return e(ctx)
}
}