💬 Что из себя представляет паттерн Circuit Breaker, применяемый в облачной разработке?
Circuit Breaker автоматически отключает сервисные функции в ответ на вероятную неисправность, чтобы предотвратить более крупные или каскадные отказы, устранить повторяющиеся ошибки и обеспечить разумную реакцию на ошибки.
📌 Компоненты
◆
◆
По сути, Circuit Breaker — это просто специализированный паттерн Adapter, в котором функция
Подобно электрическому выключателю, от которого этот паттерн получил свое название,
📌 Пример кода
Начнем с определения типа
Однако она должна включать ошибку в список возвращаемых значений:
В примере функция
Circuit Breaker автоматически отключает сервисные функции в ответ на вероятную неисправность, чтобы предотвратить более крупные или каскадные отказы, устранить повторяющиеся ошибки и обеспечить разумную реакцию на ошибки.
📌 Компоненты
◆
Circuit
— функция, взаимодействующая с сервисом.◆
Breaker
— функция-замыкание с той же сигнатурой, что и Circuit
.По сути, Circuit Breaker — это просто специализированный паттерн Adapter, в котором функция
Breaker
обертывает Circuit
и добавляет дополнительную логику обработки ошибок.Подобно электрическому выключателю, от которого этот паттерн получил свое название,
Breaker
имеет два возможных состояния: замкнуто и разомкнуто. В замкнутом состоянии все работает как обычно. Все запросы, полученные от клиента с помощью Breaker
, передаются в Circuit
без изменений, а все ответы от Circuit
возвращаются обратно клиенту. В разомкнутом состоянии Breaker
не передает запросы в Circuit
, а просто «быстро терпит неудачу», возвращая информативное сообщение об ошибке.📌 Пример кода
Начнем с определения типа
Circuit
, определяющего сигнатуру функции, которая взаимодействует с БД или другой вышестоящей службой. На практике эта сигнатура может быть любой, соответствующей нашим требованиям. Однако она должна включать ошибку в список возвращаемых значений:
type Circuit func(context.Context) (string, error)
В примере функция
Circuit
принимает экземпляр Context
. Функция Breaker
принимает любую функцию, соответствующую определению типа Circuit
, и целое число без знака, представляющее количество отказов, следующих друг за другом, после которых должно произойти автоматическое размыкание цепи. В ответ она возвращает другую функцию, которая также соответствует определению типа Circuit
:func Breaker(circuit Circuit, failureThreshold uint) Circuit {
var consecutiveFailures int = 0
var lastAttempt = time.Now()
var m sync.RWMutex
return func(ctx context.Context) (string, error) {
m.RLock() // Установить "блокировку чтения"
d := consecutiveFailures - int(failureThreshold)
if d >= 0 {
shouldRetryAt := lastAttempt.Add(time.Second * 2 << d)
if !time.Now().After(shouldRetryAt) {
m.RUnlock()
return "", errors.New("service unreachable")
}
}
m.RUnlock() // Освободить блокировку чтения
response, err := circuit(ctx) // Послать запрос, как обычно
m.Lock() // Заблокировать общие ресурсы
defer m.Unlock()
lastAttempt = time.Now() // Зафиксировать время попытки
if err != nil { // Если Circuit вернула ошибку,
consecutiveFailures++ // увеличить счетчик ошибок
return response, err // и вернуть ошибку
}
consecutiveFailures = 0 // Сбросить счетчик ошибок
return response, nil
}
}