Ответ
Преимущества:
- Независимое масштабирование: Каждый сервис можно масштабировать отдельно в зависимости от нагрузки.
- Технологическая гибкость: Разные сервисы могут быть реализованы на наиболее подходящих языках и фреймворках.
- Отказоустойчивость: Сбой одного сервиса не приводит к полному отказу всей системы.
- Независимость команд: Команды могут разрабатывать, тестировать и развертывать свои сервисы автономно.
- Лёгкость внедрения изменений: Обновление одного сервиса не требует пересборки всей системы.
Недостатки:
- Высокая сложность: Требуются дополнительные инфраструктурные компоненты: оркестратор (Kubernetes), service mesh, централизованное логирование и мониторинг.
- Накладные расходы на связь: Межсервисная коммуникация (REST, gRPC, сообщения) добавляет задержки и требует обработки сетевых ошибок.
- Сложность обеспечения согласованности данных: Транзакции, охватывающие несколько сервисов, требуют сложных паттернов (Saga, Event Sourcing).
- Сложность тестирования: End-to-end тестирование становится труднее из-за распределённой природы системы.
Пример обработки частичного отказа:
import requests
from circuitbreaker import circuitbreaker
@circuitbreaker(failure_threshold=5, recovery_timeout=60)
def get_data_from_service_b():
"""Вызов другого сервиса с использованием Circuit Breaker."""
try:
response = requests.get("http://service-b/api/data", timeout=2)
response.raise_for_status()
return response.json()
except (requests.exceptions.RequestException, requests.exceptions.Timeout):
# Логика fallback: вернуть кэшированные данные или значение по умолчанию
log.error("Service B недоступен, используется fallback")
return get_cached_data() # Стратегия отказоустойчивости
Почему это важно: Паттерн Circuit Breaker предотвращает "каскадные отказы", когда повторные вызовы падающего сервиса истощают ресурсы вызывающей стороны.