Ответ
Отказоустойчивость (fault tolerance) — это способность системы продолжать работать корректно даже при возникновении сбоев в её компонентах. Для этого применяются следующие подходы:
1. Повторные попытки (Retry)
Паттерн для автоматического повторения операции, которая завершилась неудачей из-за временной проблемы (например, сбой сети). Часто используется с экспоненциальной задержкой (exponential backoff), чтобы не перегружать отказавший сервис.
- Пример: Библиотека
tenacity.
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def call_unstable_external_service():
# Код вызова внешнего API, который может временно отказать
response = requests.get("http://example.com/api/data")
response.raise_for_status() # Вызовет исключение для кодов 4xx/5xx
return response.json()
2. Автоматический выключатель (Circuit Breaker)
Предотвращает лавинообразные отказы. Если сервис-зависимость постоянно выдает ошибки, "прерыватель" временно перестает отправлять к нему запросы, давая ему время на восстановление и немедленно возвращая ошибку клиенту.
- Пример: Библиотека
pybreaker.
from pybreaker import CircuitBreaker
# Если 5 вызовов подряд неудачны, "размыкается" на 60 секунд
db_breaker = CircuitBreaker(fail_max=5, reset_timeout=60)
@db_breaker
def get_data_from_db():
# ... код для чтения из базы данных ...
pass
3. Изоляция компонентов (Bulkhead)
Разделение системных ресурсов (пулы потоков, соединения) для разных частей приложения. Сбой в одном компоненте не должен влиять на доступность ресурсов для других.
- Реализация: Микросервисная архитектура, контейнеризация (Docker), отдельные пулы соединений к разным базам данных.
4. Резервирование и репликация (Redundancy and Replication)
Дублирование критически важных компонентов системы. Если один экземпляр выходит из строя, трафик перенаправляется на его рабочую копию.
- Примеры: Репликация баз данных (primary-replica), запуск нескольких экземпляров приложения за балансировщиком нагрузки.
5. Таймауты (Timeouts)
Установка максимального времени ожидания для любой блокирующей операции (сетевой запрос, запрос к БД). Это предотвращает "зависание" потоков в ожидании ответа от медленного или неработающего сервиса.
try:
response = requests.get(url, timeout=5) # Ждать ответа не более 5 секунд
except requests.Timeout:
logger.warning("Request timed out")
return get_fallback_data()