中文翻译暂不可用,显示俄语原文。
Настроить SLA между агентами
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить SLA между агентами
1. Цель задачи
Научиться проектировать и реализовывать надёжное взаимодействие между агентами в мультиагентной системе. Разработать механизмы таймаутов, повторных попыток (retry) и breaker|circuit breaker для вызова агента-исполнителя, обеспечив корректный fallback при его недоступности.
Ключевой результат Работающая цепочка вызовов, в которой при недоступности агента Б (или превышении SLA) автоматически срабатывает model|запасной сценарий, а система не «зависает» и логирует все сбои.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Прототип мультиагентной системы (агент А → агент Б) | Собственный учебный проект или код из предыдущих заданий |
| Агент-исполнитель (агент Б), работающий через HTTP/gRPC | Запущенный сервис с эндпоинтом (можно mock) |
| Набор тестовых запросов | Сгенерировать вручную (5–10 запросов разных типов) |
| Инструмент для создания задержек/отказов | chaos-mesh, toxiproxy или Python-декоратор time.sleep / raise |
| Инструмент для мониторинга состояния вызовов | Prometheus-метрики или просто stdout-логи с метками времени |
Если нет реального инструмента — симулируем:
- Написать простой HTTP-сервер на FastAPI, имитирующий агента Б.
- Добавить эндпоинт
/callс параметром delay иerror_probability(например, ?delay=0.5&error_prob=0.3). - Агент А обращается к агенту Б через aiohttp или httpx.
- Для breaker|circuit breaker использовать библиотеку
pybreakerили написать простой класс самому.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Агент А (оркестратор) | Python 3.11+, FastAPI / Flask, asyncio | Организация вызовов, логика таймаутов/ретраев |
| Агент Б (исполнитель) | FastAPI (или просто HTTP-сервер) | Обработка запросов, имитация сбоев |
| Клиент HTTP (async) | httpx / aiohttp | Асинхронные вызовы с таймаутами |
| Circuit breaker | pybreaker или самописный | Контроль частоты отказов |
| Мониторинг и логи | structlog + Prometheus-клиент python | Фиксация каждого вызова, времени, статуса |
| Тестирование | pytest + pytest-asyncio | Проверка сценариев падений |
| Chaos engineering | toxiproxy или декораторы | Внесение задержек и ошибок |
4. Этапы выполнения
Этап 1: Создание тестового окружения (1 час)
Действия
- Запустить два независимых FastAPI-приложения:
- Агент А (порт 8001) — будет вызывать агента Б.
- Агент Б (порт 8002) — имеет эндпоинт
/execute.
- На агенте Б добавить query-параметры:
- delay — задержка в секундах (float).
error— вероятность ошибки (0.0–1.0).
@app.get("/execute") async def execute(delay: float = 0.0, error: float = 0.0): if random.random() < error: raise HTTPException(503, "Simulated failure") await asyncio.sleep(delay) return {"status": "ok", "agent": "B"} - Проверить взаимную доступность: curl localhost:8001/health, curl localhost:8002/health.
Ожидаемый результат этапа Два работающих HTTP-сервиса, готовых к вызовам.
Этап 2: Базовая интеграция с реализацией таймаута (1 час)
Действия
- На агенте А написать функцию вызова агента Б через httpx.AsyncClient с таймаутом.
- Реализовать таймаут на уровне клиента (например, timeout=httpx.Timeout(5.0, connect=2.0)).
- Добавить логирование каждого вызова: время отправки, время ответа, статус, длительность.
- Написать простой эндпоинт
/chainна агенте А, который вызывает Б и возвращает результат или ошибку таймаута. - Тест: отправить запрос с delay=10 (больше таймаута) — агент А должен вернуть 504 или кастомный ответ.
async with httpx.AsyncClient(timeout=httpx.Timeout(5.0)) as client:
try:
resp = await client.get("http://agent-b:8002/execute", params={"delay": delay})
resp.raise_for_status()
return resp.json()
except httpx.TimeoutException:
log.warning("Timeout calling agent B")
return fallback_response()
Ожидаемый результат этапа При превышении времени ожидания агент А возвращает fallback-ответ, а не виснет.
Этап 3: Добавление ретраев (1 час)
Действия
- Реализовать стратегию повторных попыток с экспоненциальной задержкой (exponential backoff).
- Использовать tenacity либо написать свой декоратор:
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10), retry=retry_if_exception_type((httpx.TimeoutException, httpx.HTTPStatusError))) async def call_agent_b(delay): ... - Учесть: ретраи только для ошибок, которые могут быть временными (таймауты, 5xx). На 4xx ретраи не делать.
- Добавить логирование каждой попытки (номер, задержка перед ретраем).
- Тест: установить
error=0.8— проверить, что агент А делает 3 попытки, затем возвращает fallback.
Ожидаемый результат этапа Агент А автоматически повторяет запросы при сбоях, но не бесконечно.
Этап 4: Реализация Circuit Breaker (1.5–2 часа)
Действия
- Внедрить паттерн Circuit Breaker с использованием библиотеки pybreaker:
import pybreaker breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=30) - Обернуть вызов агента Б через breaker.call(call_agent_b, ...).
- Настроить три состояния:
- Closed — нормальная работа, считаем ошибки.
- Open — при превышении
fail_maxошибок за период (за 60 сек) — немедленный отказ, вызов fallback. - Half-Open — после reset_timeout пускаем один тестовый запрос, если успех → Closed, если ошибка → Open.
- Настроить логирование переключения состояний (метрика: circuit_breaker_state).
- Написать endpoint
/statusна агенте А, показывающий текущее состояние breaker. - Тесты:
- Отправить 6 запросов с ошибкой — breaker должен открыться, 7-й запрос сразу пойти в fallback.
- После reset_timeout отправить успешный запрос — breaker должен закрыться.
Ожидаемый результат этапа При частых сбоях вызовы блокируются на уровне breaker, защищая систему от каскадных отказов.
Этап 5: Интеграция SLA и финальное тестирование (1 час)
Действия
- Определить SLA для вызова агента Б:
- Max latency 3 секунды.
- Max error rate 10% за 1 минуту.
- Availability >99%.
- Реализовать метрики в Prometheus-формате:
- Написать автотест (pytest), который проверяет все сценарии:
- Нормальный вызов (без задержек) — успех.
- Медленный вызов (delay=4) — таймаут и fallback.
- С ошибкой (error=0.5) — 3 ретрая, потом fallback.
- Частые ошибки (5 подряд) — circuit breaker открывается.
- После паузы (30 сек) — проверка восстановления.
- Задокументировать поведение агента А в README.
Ожидаемый результат этапа Полная реализация SLA-механизма с метриками и автоматизированным тестом.
5. Критерии приемки (Definition of Done)
- Агент А корректно обрабатывает таймауты: при превышении лимита возвращается fallback-ответ.
- Реализованы ретраи с экспоненциальной задержкой (максимум 3 попытки).
- Circuit breaker переходит в Open после 5 последовательных ошибок.
- Fallback-сценарий выполняется при недоступности агента Б (Open breaker или таймаут после всех ретраев).
- Логирование каждого вызова включает: ID запроса, время начала/конца, статус, количество ретраев.
- Метрики (Prometheus) экспортируются, дашборд (Grafana) опционален.
- Автотест покрывает все 4 сценария (успех, таймаут, ошибка, circuit breaker).
- Код задокументирован (docstrings, README с описанием SLA и конфигурации).
- Время ответа агента А при падении агента Б не превышает 2 секунд (быстрый fallback).
6. Ожидаемый результат
Основной артефакт Репозиторий с кодом двух агентов (A и B), содержащий:
agent_a/— FastAPI приложение с интеграцией таймаутов, ретраев, circuit breaker.agent_b/— FastAPI приложение-заглушка с управляемыми сбоями.tests/— pytest-тесты всех сценариев.requirements.txtилиpyproject.toml.README.mdс описанием SLA, инструкцией по запуску и примером запроса.
Дополнительно (по желанию):
- Docker-compose для запуска всего стенда.
- Prometheus + Grafana конфиги для визуализации метрик.
- Простая нагрузочная проба (locust/siege) для проверки поведения под нагрузкой.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Агент А «зависает» при синхронном вызове | Использовать asyncio и неблокирующие HTTP-клиенты (httpx, aiohttp) |
| Некорректное поведение circuit breaker при параллельных запросах | Использовать потокобезопасный breaker (pybreaker по умолчанию thread-safe) или явно блокировать через asyncio.Lock |
| Ретраи не отличают временные ошибки от постоянных | Фильтровать исключения: только TimeoutException и 5xx; 4xx не ретраить |
| Сложно отлаживать состояние breaker | Выводить лог при каждом изменении состояния, добавить endpoint /breaker-status |
| Разные таймауты на connect, read и total | Использовать httpx.Timeout с разными параметрами; документировать каждый |
| Метрики не сходятся с реальным поведением | Вешать счётчики непосредственно перед вызовом и после (до исключения) |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Создание тестового окружения | 1 ч |
| Этап 2: Базовая интеграция + таймаут | 1 ч |
| Этап 3: Ретраи | 1 ч |
| Этап 4: Circuit Breaker | 1.5–2 ч |
| Этап 5: Интеграция + тесты | 1 ч |
| Итого | 5.5–6 ч |
Примечание: если некоторые инструменты уже знакомы, время можно сократить на 30–40%.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 12 | Как работает circuit breaker в микросервисах |
| 45 | Экспоненциальный backoff vs линейный retry |
| 67 | Паттерн Timeout в распределённых системах |
| 89 | Мониторинг SLA: метрики и алерты |
| 112 | Fallback-стратегии при недоступности сервиса |
| 134 | Chaos engineering для тестирования отказоустойчивости |
| 156 | Проектирование API с учётом SLA |
| 189 | Логирование и трейсинг в мультиагентных системах |
| 210 | Prometheus histogram для задержек запросов |
| 245 | Graceful degradation: как снижать качество, а не ломаться |
10. Чек-лист самопроверки
- Я настроил таймаут на HTTP-клиенте и убедился, что при задержке > SLA возвращается fallback.
- Я реализовал ретраи с ограничением по числу попыток и экспоненциальной задержкой.
- Я добавил circuit breaker и проверил его работу: после N ошибок вызовы идут в fallback без попытки.
- Я написал хотя бы 3 автотеста, покрывающих разные сценарии (успех, сбой, broken circuit).
- Я задокументировал SLA и параметры конфигурации в README.
- Я проверил, что время ответа агента А при недоступности Б не превышает 2 секунд.
- Я настроил логирование состояния breaker и количества ретраев.
- Я убедился, что метрики (экспортируются в Prometheus) корректно отражают число запросов и их статусы.