Ответ
Микросервисная архитектура потенциально более отказоустойчива, чем монолитная, но эта отказоустойчивость достигается за счет усложнения системы и внедрения специальных паттернов.
Микросервисы
- Преимущество (Изоляция сбоев): Ключевое достоинство — сбой одного сервиса не приводит к отказу всей системы. Например, если сервис рекомендаций недоступен, пользователи все еще могут просматривать каталог товаров и оформлять заказы.
- Сложность: Для достижения отказоустойчивости необходимо реализовывать дополнительные паттерны:
- 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}")
Вывод: Микросервисы предоставляют более мощные инструменты для построения отказоустойчивых систем, но требуют значительно больших инженерных усилий. Для небольших проектов монолит может быть более прагматичным выбором.