Обеспечение надежного и предсказуемого поведения приложений.

(Микро)сервисы могут взаимодействовать друг с другом, выполняя синхронные вызовы HTTP (или вызовы gRPC):

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

Тайм-аут

Чем дольше клиентский микросервис ожидает ответа, тем меньше вероятность того, что он получит успешный ответ. По истечении определенного периода времени обычно нет смысла продолжать ждать ответа от удаленного, поэтому используются тайм-ауты, чтобы прекратить ожидание ответа.

При реализации шаблона тайм-аута учитывайте как минимум следующие факторы:

  • Интервал ожидания. В некоторых случаях, когда ожидаемое время отклика невелико, время ожидания может составлять 5 секунд, в других — 30 секунд и более. Интервал тайм-аута следует выбирать в каждом конкретном случае.
  • Типы тайм-аута. При настройке интервала тайм-аута важно понимать, к какому типу тайм-аута будет применяться этот параметр. Например, существуют тайм-аут соединения и тайм-аут запроса. Разработчик может подумать, что устанавливает таймаут для запроса, но на самом деле он будет применяться к соединению или наоборот.
  • Настраиваемость. Рассмотрите возможность установки значения времени ожидания в файлах конфигурации вместо жесткого кодирования.

Повторить шаблон

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

Высоки шансы, что временный сбой исчезнет после второй или более попыток, и, наконец, вызов будет успешным.

При реализации шаблона повторных попыток учитывайте как минимум следующие факторы:

  • Выберите только типы временных ошибок, чтобы повторить попытку. Логика повтора должна повторять запросы только после того, как произошел временный сбой, который представлен этими кодами состояния в случае HTTP-вызовов: 429 (слишком много запросов), 503 (служба недоступна) или другие. Однако такие ответы, как 400 (неверный запрос), 403 (запрещено), 500 (внутренняя ошибка сервера), восстановлению не подлежат, поэтому логика повторных попыток не должна повторять их.
  • Максимальное количество попыток. Клиент может повторять неудачные вызовы неограниченное количество раз, но это может привести к бесконечной работе. Максимальное количество попыток обычно варьируется от 3 до 5.
  • Интервал между попытками. Интервал не должен быть слишком коротким, чтобы дать удаленной службе возможность восстановиться, но он также не должен быть достаточно длинным, чтобы существенно повлиять на производительность системы.
  • Линейная отсрочка против экспоненциальной отсрочки. При линейной отсрочке интервал ожидания между повторными попытками фиксирован, а при экспоненциальной отсрочке интервал ожидания увеличивается после каждой повторной попытки.

Автоматический выключатель

Иногда шаблон повторных попыток не является идеальным механизмом восстановления после сбоев. В основном это связано с двумя вещами:

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

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

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

Резервное действие

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

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

Отсутствие должным образом определенного резервного действия может привести к ошибкам, которые трудно расследовать.

Кэширование

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

Что следует учитывать при реализации кэша для уменьшения количества сетевых вызовов:

  • Как долго данные должны оставаться в кеше до истечения срока действия? Срок действия будет зависеть от таких факторов, как частота обновлений данных в удаленной микрослужбе и/или как долго клиентская микрослужба может использовать устаревшие данные из локального кэша.
  • Должны ли данные кэшироваться в локальном кэше службы или на удаленном сервере кэширования, таком как Redis? Такие условия, как необходимость хранения больших данных, масштабирование экземпляров микросервиса и некоторые другие, обычно приводят к необходимости использования удаленного кэширующего сервера. Подробнее об этом можно прочитать в моей другой статье о кэшировании.

Последние мысли

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

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

Спасибо за прочтение. Если вам понравилось то, что вы прочитали, ознакомьтесь с этой историей ниже:



Подпишитесь на мой канал в Telegram Software Development Daily, чтобы получать от меня больше контента.

Также подумайте о том, чтобы стать участником Medium.