Sobes.tech
Back to questions
Senior
4

Балансер должен понимать, что бэкенд отвечает ошибками, и при превышении порога на определённое время исключать его из балансировки (Circuit Breaker)

Companies where asked
Яндекс

Answer from AI

sobes.tech AI

Для реализации балансировщика с поддержкой Circuit Breaker на Go нужно отслеживать состояние каждого бэкенда и учитывать количество ошибок за определённый период. При превышении порога ошибок сервис помечается как "отключённый" и исключается из балансировки на время.

Основные шаги:

  1. Хранить для каждого бэкенда счётчик ошибок и состояние (Closed, Open, Half-Open).
  2. При ошибках увеличивать счётчик.
  3. Если количество ошибок превышает порог за заданный интервал, переводить состояние в Open — бэкенд исключается.
  4. Через некоторое время переводить в Half-Open — пробовать отправлять запросы.
  5. Если запросы успешны — переводить в Closed, сбрасывая счётчики.

Пример упрощённой структуры:

type CircuitBreaker struct {
    failureCount int
    state        string // "Closed", "Open", "Half-Open"
    lastFailure  time.Time
    mutex        sync.Mutex
}

func (cb *CircuitBreaker) AllowRequest() bool {
    cb.mutex.Lock()
    defer cb.mutex.Unlock()
    if cb.state == "Open" && time.Since(cb.lastFailure) < cooldown {
        return false
    }
    if cb.state == "Open" {
        cb.state = "Half-Open"
    }
    return true
}

func (cb *CircuitBreaker) ReportResult(success bool) {
    cb.mutex.Lock()
    defer cb.mutex.Unlock()
    if success {
        cb.failureCount = 0
        cb.state = "Closed"
    } else {
        cb.failureCount++
        cb.lastFailure = time.Now()
        if cb.failureCount >= failureThreshold {
            cb.state = "Open"
        }
    }
}

Балансер при распределении запросов проверяет AllowRequest() для каждого бэкенда и исключает те, у которых состояние "Open".