Шаблон проектирования 2: Что такое шаблон автоматического выключателя? Как это использовать?

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

Проблема

Приложения, которые зависят от внешних зависимостей, таких как другие приложения, базы данных и т. д., будут иметь больше потенциальных областей, в которых что-то может пойти не так. Эти ошибки могут быть вызваны временными сетевыми проблемами, тайм-аутами, регулированием и т. д. В таких случаях вы должны использовать шаблон повторных попыток, поскольку запросы, скорее всего, будут успешными при повторной попытке. Но в случаях, когда зависимость не работает в течение более длительного периода, мы хотели бы иметь возможность обнаруживать это, а не просто повторять каждый отдельный вызов этой зависимости, особенно если у нас есть цепные запросы. Это может иметь большое влияние на остальную часть приложения, если запросы повторяются для зависимости, которая продолжает давать сбой. См. этот пример из моей статьи о шаблоне повторных попыток:

Рассмотрим пример ниже. Мы видим, что служба A вызывает службу B, которая вызывает службу C, которая вызывает базу данных. Представьте, что каждая служба реализует шаблон повторных попыток для каждой из своих зависимостей с верхним пределом в 5 повторных попыток. Если база данных не работает или занята, служба C попытается вызвать ее 5 раз, прежде чем сбой при каждом вызове службы B. И как мы видим, служба B пытается вызвать службу C 5 раз, прежде чем потерпеть неудачу, и если все 5 вызовов службы C из службы B завершатся неудачно, мы попытаемся вызвать базу данных 5*5=25 раз. А если добавить службу A, которая также использует шаблон повторных попыток для службы B, один вызов службы A может привести к 5*5*5=125 запросам к базе данных.

Как это решить

Автоматический выключатель и схема повторных попыток в чем-то похожи. Они оба обнаруживают поведение системных зависимостей и воздействуют на них соответствующим образом. Но ключевое различие между ними заключается в том, что шаблон повторных попыток определяет, будет ли неудачная операция успешной при повторной попытке, и если да, то она повторяет попытку. Шаблон автоматического выключателя определяет вероятность сбоя неудачной операции при повторной попытке и, если да, вместо этого происходит быстрый сбой.

При реализации прерывателя цепи вы хотите, чтобы все ваши запросы к внешним зависимостям проходили через этот компонент. Затем задача автоматического выключателя состоит в том, чтобы отслеживать количество отказов по различным зависимостям. Пока количество недавних сбоев не свидетельствует об общей проблеме с зависимостью, прерыватель цепи замкнут и запросы могут проходить через него. Но если количество недавних сбоев в отношении зависимости превысит определенный порог, прерыватель цепи откроется, что означает, что он не пропустит никакие запросы к неисправной зависимости. Вместо этого он пощадит вызовы, так как они, скорее всего, завершатся неудачно, и вместо этого выдаст исключения и быстро выйдет из строя. Вы можете подумать, что я случайно поменял местами значения двух состояний, но считайте это переключением. Когда переключатель разомкнут, электричество не течет, но есть, когда он замкнут.

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

Как выбрать правильный порог отказа и значение таймера, во многом зависит от зависимости, которую вы защищаете. Порог отказа должен основываться на том, как обычно действует зависимость. Вы можете получить общее представление об этом, покопавшись в журналах или настроив мониторинг, если у вас его еще нет. Период между открытым и полуоткрытым состоянием немного сложнее. Недоступность зависимости может сильно различаться в зависимости от причины, по которой она недоступна. Иногда это может быть вызвано простым перезапуском, а иногда это могут быть более серьезные проблемы, для устранения которых требуется больше времени. Ключевым моментом является выбор временного интервала, при котором прерыватель цепи заблокирует запрос с наибольшей вероятностью, даже если зависимость снова стала доступной, при этом количество запросов остается минимальным. Если вы не контролируете зависимость, вам придется принять квалифицированное решение на основе типичного шаблона этой зависимости. Но если вы контролируете ситуацию, вы можете проявить немного больше творчества. Например, зависимость может опубликовать событие в теме, когда она запустится, и приложение с автоматическим выключателем может подписаться на эту тему, тогда автоматический выключатель может перейти в полуоткрытое состояние при появлении этого события. Это сводит к минимуму риск блокировки запросов автоматическим выключателем, даже если зависимость снова активна.

В зависимости от типа операции, которую блокирует ваш автоматический выключатель, существуют способы предотвратить передачу ошибки клиенту. Рассмотрим конечную точку для создания заказа. Может случиться так, что зависимость для хранения заказа недоступна в тот момент, когда клиент инициирует операцию, но вместо того, чтобы отклонить запрос клиента, вы можете сохранить данные заказа где-то в другом месте, чтобы они были подобраны позже. когда автоматический выключатель снова замкнут.

Заключение

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

Обязательно потратьте некоторое время на определение правильного порога отказа и временного интервала между переходом из открытого состояния в полуоткрытое. Кроме того, не забывайте постоянно отслеживать, чтобы определить, следует ли изменить какую-либо из этих конфигураций.

Спасибо за чтение.

Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку здесь.