hw-07-08-distributed-patterns-clowvwnnn
Описание
Языки
- Python21,8%
- Rust21,2%
- Go20,9%
- C++18,1%
- Dockerfile12,7%
- CMake5,3%
Домашнее задание №7: Паттерны отказоустойчивости (Resilience)
Тема: Паттерны распределенных систем и Observability.
Цель: Сделать gRPC-клиент надежным в условиях нестабильной сети и сбоев сервера.
Архитектура и Легенда
У нас есть система из двух сервисов:
- Unstable Server (Сервер): Имитирует нестабильную работу (Payment Gateway, Legacy System).
- В режиме
он периодически зависает на 5 секунд или возвращает ошибки.CHAOS_MODE=true
- В режиме
- Resilient Client (Клиент): Ваш сервис, который должен обращаться к серверу.
Проблема: Текущая реализация клиента (или стандартная библиотека gRPC) не готова к сбоям. При зависании сервера клиент вечно ждет ответа, блокируя потоки, или падает при первой же ошибке.
Ваша задача: Реализовать на стороне клиента паттерны Timeout, Retry (с Exponential Backoff) и Circuit Breaker.
Как начать
Выберите язык реализации
Проект содержит заготовки для четырех языков. Выберите один, на котором будете выполнять задание.
- Python:
(Рекомендуется для быстрого старта). Используетpython/.uv - Go:
. Использует стандартный тулчейн Go.go/ - C++:
. Использует фреймворк userver и CMake.cpp/ - Rust:
. Использует Tonic и Cargo.rust/
Настройка окружения
Python (uv)
Если вы выбрали Python, убедитесь, что установлен uv.
Docker Compose
Для запуска всей системы (клиент + сервер + мониторинг) используется Docker.
По умолчанию в
включен Python-сервер и Python-клиент. Если вы пишете на другом языке, отредактируйте секциюdocker-compose.ymlв файлеservices.client.docker-compose.yml
Задания
Часть 1: Реализация Паттернов (Обязательно)
Вам необходимо отредактировать файл клиента (например, или конфиг ) и внедрить следующие механики:
-
Timeout (Таймаут):
- Установите жесткий лимит ожидания ответа от сервера (2 секунды).
- Проверка: Сервер в хаос-режиме иногда спит 5 секунд. Клиент не должен ждать, а должен падать с ошибкой
через 2 секунды.DeadlineExceeded
-
Retry (Повторные попытки):
- Если получена ошибка сети или
, повторите запрос.UNAVAILABLE - Используйте Exponential Backoff: задержка между попытками должна расти (например, 1с -> 2с -> 4с).
- Ограничьте количество попыток (например, 3 раза).
- Если получена ошибка сети или
-
Circuit Breaker (Предохранитель):
- Если сервер вернул ошибку 5 раз подряд, клиент должен перейти в состояние
.Open - В этом состоянии запросы не отправляются в сеть, а сразу возвращается ошибка.
- Через 30 секунд (Recovery Timeout) клиент должен попробовать сделать один запрос (
).Half-Open
- Если сервер вернул ошибку 5 раз подряд, клиент должен перейти в состояние
Часть 2: Observability (Дополнительное задание)
- Запустите Prometheus и Grafana (раскомментируйте их в
).docker-compose.yml - Настройте экспорт метрик из вашего клиента.
- Постройте дашборд в Grafana, показывающий:
- RPS (Requests Per Second).
- Количество ошибок.
- Состояние Circuit Breaker (Closed/Open).
Подсказки по языкам
Python
- Используйте декораторы
из библиотеки@retry.tenacity - Используйте
из библиотеки@circuit.circuitbreaker - Не забудьте сгенерировать proto-код:
.cd python && uv run python src/codegen.py
Go
- Используйте библиотеку
для Circuit Breaker.gobreaker - Retry лучше реализовать явным циклом
для понимания работы Backoff.for
C++ (userver)
- Вам не нужно писать код C++. Вам нужно правильно настроить
.cpp/configs/config.yaml - Найдите в документации userver параметры
(attempts, timeout) иqos.congestion-control
Rust
- В папке
лежит общий контракт.protoавтоматически скомпилирует его.build.rs - Для Retry и Timeout можно использовать крейт
(Middleware) или реализовать логику вручную вtower.client.rs
Критерии приемки
- Pull Request с реализованным кодом.
- В README вашего форка приложены скриншоты логов, где видно:
- Как клиент делает 3 попытки перед тем, как сдаться (Retry).
- Как клиент перестает слать запросы после серии неудач (Circuit Breaker).
- (Бонус) Скриншот дашборда Grafana.