Какая архитектура более отказоустойчива: микросервисная или монолитная

Ответ

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

Микросервисы

  • Преимущество (Изоляция сбоев): Ключевое достоинство — сбой одного сервиса не приводит к отказу всей системы. Например, если сервис рекомендаций недоступен, пользователи все еще могут просматривать каталог товаров и оформлять заказы.
  • Сложность: Для достижения отказоустойчивости необходимо реализовывать дополнительные паттерны:
    • Service Discovery: Автоматическое обнаружение работающих экземпляров сервисов.
    • Circuit Breaker (Предохранитель): Временное прекращение запросов к отказавшему сервису, чтобы дать ему время на восстановление и не тратить ресурсы на заведомо неудачные вызовы.
    • Retry (Повторные попытки): Автоматический повтор запроса в случае временной сетевой ошибки.
    • Health Checks: Регулярные проверки работоспособности сервисов.

Монолит

  • Недостаток (Единая точка отказа): Необработанная ошибка или утечка памяти в одном из модулей может привести к отказу всего приложения. Все компоненты тесно связаны и работают в одном процессе.
  • Преимущество (Простота): Отказоустойчивость в рамках одного процесса реализовать проще (например, через try-catch), но последствия сбоя гораздо серьезнее.

Пример реализации паттерна Retry в Python с библиотекой tenacity:

Этот паттерн помогает справиться с временными сбоями при вызове другого сервиса.

from tenacity import retry, stop_after_attempt, wait_fixed
import requests

# Декоратор @retry будет повторять вызов функции до 3 раз
# с интервалом в 2 секунды, если она вызывает исключение.
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def get_payment_status(order_id):
    print(f"Попытка получить статус для заказа {order_id}...")
    # Этот вызов может временно не работать
    response = requests.get(f"http://payment-service/orders/{order_id}")
    response.raise_for_status() # Вызовет исключение для кодов 4xx/5xx
    return response.json()

try:
    status = get_payment_status("123-abc")
    print("Статус получен успешно:", status)
except Exception as e:
    print(f"Не удалось получить статус после нескольких попыток: {e}")

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