Читаем Создание микросервисов полностью

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

Рис. 11.2. Обзор предохранителей

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

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

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

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

Переборки

В книге Release It! Нигард дает описание концепции переборок, применяемых в качестве способа изоляции от сбоев. В судостроении переборка является составной частью корабля, которую можно закрыть для защиты помещений корабля от поступления забортной воды. Если корабль дает течь, можно закрыть двери переборки. Часть корабля затопится водой, но все остальное будет не тронуто.

В понятиях архитектуры программ можно рассматривать множество различных переборок.

Возвращаясь к моему личному опыту, мы упустили шанс реализации переборки. Нам нужно было для каждого нижестоящего соединения использовать различные пулы соединений. Таким образом, при исчерпании одного пула соединений это не влияло бы на остальные соединения (рис. 11.3). Существовала бы гарантия того, что замедление работы нижестоящего сервиса повлияет только на один пул соединения, позволяя нормально обрабатывать другие вызовы.

Рис. 11.3. Использование по одному пулу соединения для каждого нижестоящего сервиса с целью создания переборок

Еще одним способом реализации переборок может стать разделение проблем. Разделением функций на отдельные микросервисы можно уменьшить влияние сбоя в одной области на работу других областей.

Внимательно изучите все стороны вашей системы, от которых можно ожидать сбоя, как внутри микросервисов, так и между ними. Установлены ли между ними переборки? Советую начать с разделения пулов соединений, выделяя отдельный пул для каждого нижестоящего соединения. Но можно пойти и дальше и рассмо­треть также возможность применения предохранителей.

Перейти на страницу:

Похожие книги