Как отказ одного сервиса становится проблемой для всей системы

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

Как запускается каскад

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

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

Почему трудно найти начало цепочки

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

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