Перейти к содержанию

Circuit Breaker

Чем полезен?

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

Задачи Circuit Breaker:

  1. Нужно дать источнику данных восстановиться, останавливая на какое-то время запросы к нему.
  2. В случае остановки запросов к целевому сервису, нужно отдавать, пусть не самые последние, но всё ещё актуальные данные.
  3. В случае недоступности целевого сервиса и отсутствия актуальных данных, предусмотреть стратегию поведения. Например, возврат значения по умолчанию или другую стратегию, подходящую для конкретного случая.

Когда стоит использовать?

  1. Для предотвращения попыток обращения к сервису или разделяемым ресурсам, когда вероятность возникновения ошибки высока и эти ошибки имеют продолжительный характер.

Когда не стоит использовать?

  1. Для обращения к приватным ресурсам приложения — это даст только дополнительный overhead.
  2. Как замена обработки исключений бизнес-логики приложения.

Состояния

  1. Closed: запрос от приложения направляется напрямую к сервису. Счётчик ошибок = 0 и приложение функционирует как обычно.
  2. Open: запрос от приложения немедленно завершается с ошибкой и исключение возвращается в приложение.
  3. Half-Open: ограниченному количеству запросов от приложения разрешено обратиться к сервису. Если эти запросы успешны, то считаем, что предыдущая ошибка исправлена и прокси-сервис переходит в состояние Closed. Счётчик ошибок сбрасывается на 0.
  4. Если любой из запросов завершился с ошибкой, то считается, что ошибка всё ещё присутствует. Тогда прокси-сервис возвращается в состояние Open и перезапускает таймер, чтобы дать системе дополнительное время на восстановление после сбоя.
flowchart TD

title[<u>Circuit Breaker State Diagram</u>]
title---A
style title fill:#FFF,stroke:#FFF
linkStyle 0 stroke:#FFF,stroke-width:0;

classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow

  A[Closed] -- failure rate above a threshold --> B[Open];
  B -- after wait duration ---> C[Half-Open];
  C -- failure rate above a threshold ---> B;
  C -- failure rate below a threshold ----> A;

 class B badBadEvent