Архитектура бэкенда
Circuit breakers: тест с выбором ответа
Шесть вопросов поперёк всего юнита. Каждый отражает решение, которое ты принимаешь в реальном инциденте — не определение для заучивания, а компромисс, который надо взвесить, когда downstream болен, а твои потоки заполняются.
Убедись, что связываешь fast-fail, машину состояний, пороги срабатывания, bulkheads, fallback’и и сбои на масштабе флота — тот синтез, к которому вели отдельные уроки.
Платёжный провайдер замедляется с 50 мс до 5 с, но не возвращает ошибок. За секунды весь сервис — включая маршруты, которые не трогают платежи — перестаёт отвечать. Почему медленный случай хуже полного отказа и какова роль breaker'а?
Breaker настроен с cooldown (resilience4j waitDurationInOpenState) в 1 с перед зависимостью, которой нужно около 20 с на перезапуск после падения. Что идёт не так?
Низконагруженный admin-эндпоинт видит около 10 запросов/минуту. Один транзиентный timeout в 3 часа ночи срабатывает его breaker на весь cooldown, быстро отказывая каждому последующему запросу из-за единственного блипа. Какая настройка — правильный фикс, и почему не просто поднять failure-rate threshold?
Три downstream'а — платежи, рекомендации, поиск — делят один пул из 50 потоков. Рекомендации (наименее важные) замедляются до 5 с, и весь сервис падает, хотя их breaker в итоге срабатывает. Что добавляет bulkhead, чего breaker сам по себе не может?
Команда оборачивает шаткий сервис рекомендаций в breaker и выкатывает. В следующий инцидент breaker не срабатывает, а главная страница висит — вызовы рекомендаций не ошибаются, они занимают по 30 с каждый. Чего не хватает и какой второй кусок ещё нужен, когда breaker сработает?
Сервис A зовёт B зовёт C, каждый ретраит до 4 раз при отказе, на флоте из пятидесяти инстансов. C коротко вздрагивает. Дрожь превращается в устойчивый самонаведённый сбой. Каков доминирующий механизм и какой фикс его ограничивает?
Сквозная линия юнита — одна цепочка решений: медленная зависимость голодит общий пул, поэтому breaker быстро отказывает ей (closed считает отказы, open отвергает мгновенно, half-open зондирует), срабатывая на failure rate по скользящему окну с минимальным порогом объёма, причём медленное считается отказом. Bulkhead изолирует бюджет на зависимость, чтобы один больной downstream не осушил весь пул до срабатывания реактивного breaker’а; timeout превращает зависание в считаемый отказ, а fallback решает, что вернуть, когда открыт; на масштабе флота реальная опасность — retry amplification (4×4×4 = 64), укрощаемая держанием breaker’а над ретраями, ограничением абсолютного rate ретраев и jitter’ом и ретраев, и half-open проб. У каждого пер-инстансового защитного устройства должна быть история на уровне флота.