Зависимость восстановилась после срабатывания размыкателя, но новые вызовы всё ещё блокируются. Как механизм half-open позволяет безопасно возобновить трафик?
В состоянии half-open размыкатель пропускает к зависимости только ограниченное число пробных вызовов. Если они успешно завершаются в заданных пределах задержки и ошибок, размыкатель возвращается в состояние closed; при новом сбое снова переходит в open. Это предотвращает преждевременный выпуск всего накопившегося трафика на ещё нестабильную зависимость.
Паттерн circuit breaker появился как практический ответ на каскадные отказы при взаимодействии через ненадёжные удалённые вызовы. Его задача — не только прекращать бесполезные обращения, но и контролируемо проверять восстановление зависимости без ручного вмешательства.
Обычный таймер после открытия размыкателя недостаточен: по его истечении зависимость может быть ещё перегружена или частично неисправна. Состояние half-open добавляет отдельный этап проверки перед полным восстановлением трафика.
Если после периода блокировки сразу разрешить всем запросам обращаться к зависимости, возникнет всплеск нагрузки. Он способен повторно вызвать таймауты, заполнить пулы соединений и вернуть систему в состояние каскадного отказа.
Если же никогда не разрешать пробные вызовы, размыкатель останется открытым даже после восстановления зависимости. Поэтому нужно одновременно ограничить объём проверки, определить критерии успеха и исключить конкурирующие переходы состояний.
Размыкатель обычно имеет три состояния:
В half-open часто допускают один или небольшую фиксированную группу пробных запросов, а остальные сразу отклоняют либо направляют в fallback. Пробный вызов должен иметь собственный жёсткий таймаут: иначе зависшая зависимость будет удерживать ресурсы и не позволит принять решение.
Критерий перехода в closed должен учитывать не только факт успешного ответа, но и приемлемую задержку, корректный статус и иногда несколько последовательных успешных проб. Если проба завершается ошибкой или превышает таймаут, размыкатель возвращается в open, обычно начиная новый cooldown-период.
Нужно защищаться от гонки нескольких потоков или экземпляров, одновременно решающих открыть проверочное окно. Для локального размыкателя применяют атомарное управление состоянием; для общего распределённого состояния требуется отдельная координация, но она сама становится зависимостью и источником задержек.
Слишком короткий cooldown создаёт частые бесполезные пробы, а слишком длинный увеличивает период деградации после реального восстановления. Малое число проб снижает риск повторной перегрузки, но повышает вероятность ошибочно признать зависимость неисправной из-за случайного сбоя; большое число даёт более надёжную оценку, но создаёт дополнительную нагрузку.
Размыкатель не заменяет таймауты, ограничение параллелизма, повторные попытки с бюджетом и резервный сценарий. В частности, повторные попытки внутри пробного окна могут исказить результат: одна внешняя проба способна породить много реальных запросов к ещё не восстановившейся зависимости.
Сервис оформления заказа обращается к внешнему сервису расчёта доставки. После серии таймаутов размыкатель открылся на 30 секунд. Вариант с немедленным возвратом в closed привёл бы к тому, что все запросы за 30 секунд одновременно создали новый поток обращений; вариант без автоматической проверки потребовал бы ручного сброса состояния и дольше сохранял бы деградацию.
Было выбрано half-open с одним пробным запросом, таймаутом короче пользовательского дедлайна и переходом в closed только после трёх успешных проб с допустимой задержкой. Остальные запросы в это время получали расчёт доставки из кэша либо понятный fallback. Такой вариант ограничил нагрузку на внешнюю систему и позволил автоматически восстановить обычный трафик после подтверждения стабильности.
Обычно нет. Один успех может быть случайным и не показывать, что зависимость выдерживает нормальную задержку или несколько последовательных обращений. Число проб, окно наблюдения и критерии перехода выбирают по уровню риска, стоимости вызова и характеру отказов; для критичной зависимости полезнее требовать серию успешных проб.
Каждый экземпляр может открыть собственное пробное окно, поэтому суммарная нагрузка окажется намного выше ожидаемой. Это допустимо только при контролируемом количестве клиентов; иначе применяют локальный лимит с учётом общего бюджета, координацию проб или распределённый механизм, оценивая его дополнительную сложность и собственную отказоустойчивость.
Зависимость может отвечать быстро на малое число проб, но оставаться перегруженной при рабочей конкуренции. Поэтому кроме успешности учитывают p95 или p99 задержки, долю ошибок, ограничение параллелизма и иногда постепенное увеличение трафика. Полное восстановление должно подтверждаться поведением зависимости под контролируемой, а не мгновенно максимальной нагрузкой.