В микросервисной архитектуре: что произойдет при отказе (failure) одного из сервисов?

«В микросервисной архитектуре: что произойдет при отказе (failure) одного из сервисов?» — вопрос из категории Архитектура, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Возможные сценарии:

Сценарий (без resilience) Результат
Прямой вызов упавшего сервиса Клиент получает ошибку (HTTP 5xx, таймаут, исключение).
Сервис является upstream-зависимостью Каскадный сбой: ошибка распространяется на вызывающие сервисы.

Паттерны для повышения устойчивости (Resilience):

  1. Повторные попытки (Retry):

    • Цель: Временные сбои (сеть, таймаут).
    • Реализация: @Retryable в Spring Retry, настройки в HTTP-клиентах.
      @Retryable(value = {ServiceUnavailableException.class}, maxAttempts = 3)
      public String callExternalService() { ... }
  2. Аварийный выключатель (Circuit Breaker):

    • Цель: Предотвратить каскадные сбои и дать сломанному сервису время на восстановление.
    • Состояния: CLOSED (норма), OPEN (блокировка вызовов), HALF_OPEN (пробные запросы).
    • Реализация: Resilience4j, Spring Cloud Circuit Breaker.
  3. Запасной вариант (Fallback):

    • Цель: Вернуть клиенту приемлемый ответ при ошибке (кэш, заглушка, упрощенная логика).
      
      @CircuitBreaker(name="myService", fallbackMethod = "fallbackResponse")
      public String getData() { ... }

    public String fallbackResponse(Exception e) { return "Cached or default data"; }

  4. Балансировка нагрузки и health checks:

    • Цель: Исключить нездоровые инстансы из пула маршрутизации (например, в Kubernetes или через Eureka/Ribbon).

Общие рекомендации:

  • Внедрите централизованное логирование и мониторинг (ELK Stack, Prometheus, Grafana).
  • Настройте оповещения на основе метрик и логов.
  • Используйте асинхронную коммуникацию (очереди) для снижения связности.
  • Реализуйте Graceful Shutdown, чтобы завершающийся сервис не обрывал активные запросы.