Ответ
Паттерн Circuit Breaker (Предохранитель) — это механизм защиты, который предотвращает каскадные сбои в распределенных системах. Он отслеживает ошибки при вызове удаленного сервиса и, если их количество превышает порог, временно "разрывает цепь", прекращая дальнейшие вызовы и немедленно возвращая ошибку.
Состояния (States):
- Closed (Замкнуто): Начальное состояние. Запросы свободно проходят к удаленному сервису. Каждый сбой инкрементирует счетчик ошибок.
- Open (Разомкнуто): Если счетчик ошибок достигает заданного порога, "предохранитель" переходит в это состояние. Все последующие запросы немедленно отклоняются с ошибкой, без попытки вызова сервиса. Запускается таймер сброса.
- Half-Open (Полуоткрыто): По истечении таймера сброса "предохранитель" переходит в это состояние. Он пропускает один тестовый запрос к сервису. Если запрос успешен — цепь замыкается (переход в
Closed
). Если неудачен — цепь снова размыкается (возврат вOpen
), и таймер сброса запускается заново.
Пример потокобезопасной реализации на Go:
import (
"errors"
"sync"
"time"
)
// Константы для состояний
const (
StateClosed = "closed"
StateOpen = "open"
StateHalfOpen = "half-open"
)
type CircuitBreaker struct {
mu sync.Mutex
state string
failures int
threshold int // Порог ошибок для размыкания
resetTimeout time.Duration // Таймаут перед переходом в Half-Open
lastFailureTime time.Time
}
func (cb *CircuitBreaker) Call(f func() error) error {
cb.mu.Lock()
if cb.state == StateOpen {
if time.Since(cb.lastFailureTime) > cb.resetTimeout {
cb.state = StateHalfOpen
} else {
cb.mu.Unlock()
return errors.New("circuit is open")
}
}
cb.mu.Unlock()
err := f()
cb.mu.Lock()
defer cb.mu.Unlock()
if err != nil {
cb.failures++
if cb.state == StateHalfOpen || cb.failures >= cb.threshold {
cb.state = StateOpen
cb.lastFailureTime = time.Now()
}
return err
}
// При успехе сбрасываем счетчик и замыкаем цепь
cb.failures = 0
cb.state = StateClosed
return nil
}
Преимущества:
- Отказоустойчивость: Предотвращает выход из строя всей системы из-за одного неисправного компонента.
- Быстрый отказ (Fast Fail): Не тратит ресурсы на заведомо провальные вызовы.
- Graceful Degradation: Позволяет системе продолжать работать, пусть и с ограниченной функциональностью.