English translation is not available yet. Showing Russian content.
Что такое circuit breaker и как он применяется к LLM API вызовам?
Краткий тезис
Circuit breaker (автоматический выключатель) — это паттерн отказоустойчивости, который предотвращает каскадные сбои в распределённых системах. Применительно к LLM API вызовам он защищает приложение от перегрузки внешнего сервиса (например, OpenAI, Anthropic) при превышении порога ошибок (timeout, 5xx, rate limit). Когда число ошибок превышает заданный порог, цепь «размыкается» — все последующие вызовы мгновенно возвращают fallback-ответ (кэш, заглушка, альтернативная модель) без реального запроса к API, давая сервису время восстановиться.
1. Термин: Circuit Breaker (автоматический выключатель)
Circuit breaker — это паттерн, заимствованный из электротехники. В программных системах он отслеживает количество неудачных вызовов внешнего ресурса и при превышении порога временно блокирует дальнейшие вызовы, чтобы избежать бесполезной нагрузки и каскадных отказов.
Ключевые понятия
- Состояния breaker|circuit breaker
- Closed (замкнут) — нормальный режим, вызовы проходят, ошибки считаются.
- Open (разомкнут) — порог ошибок превышен, вызовы блокируются, возвращается fallback.
- Half-Open (полуоткрыт) — через заданный таймаут breaker|circuit breaker пропускает ограниченное число пробных вызовов, чтобы проверить, восстановился ли сервис.
- Fallback — альтернативное действие при разомкнутой цепи (возврат кэша, заглушки, вызов другой модели).
- Порог ошибок (error threshold) — количество или процент ошибок за окно времени, при котором цепь размыкается.
- Таймаут восстановления (reset timeout) — время, через которое circuit breaker переходит в half-open.
2. Состояния и переходы circuit breaker
| Состояние | Действие при вызове | Условие перехода |
|---|---|---|
| Closed | Выполняется реальный запрос к API. Счётчик ошибок увеличивается при неудаче. | Если число ошибок за окно (например, 5 ошибок за 10 секунд) превышает порог → переход в Open. |
| Open | Все вызовы мгновенно возвращают fallback (без запроса к API). | По истечении reset timeout (например, 30 секунд) → переход в Half-Open. |
| Half-Open | Пропускается ограниченное число пробных вызовов (обычно 1–3). | Если пробные вызовы успешны → переход в Closed; если хотя бы один неудачен → возврат в Open (сброс таймера). |
Графическое представление
Closed → (ошибки > порог) → Open → (таймаут) → Half-Open → (успех) → Closed
↓ (неудача)
Open
3. Параметры circuit breaker для LLM API
При настройке circuit breaker для LLM вызовов важно учитывать специфику API:
| Параметр | Типичное значение | Пояснение |
|---|---|---|
| Error threshold | 3–5 ошибок за 1 минуту | Учитываются timeout (>30 сек), HTTP 429 (rate limit), 5xx (серверные ошибки). |
| Reset timeout | 30–60 секунд | Время, которое даётся API на восстановление. |
| Half-open max calls | 1–2 | Один пробный запрос, чтобы не перегрузить сервис. |
| Success threshold | 1–2 подряд успешных вызова | Закрытие цепи после восстановления. |
| Sliding window | 10 секунд – 1 минута | Окно, в котором считаются ошибки (скользящее или фиксированное). |
Важно Для LLM API часто используют exponential backoff вместе с circuit breaker, чтобы не создавать лавину повторных запросов после восстановления.
4. Применение circuit breaker к LLM API вызовам
4.1 Зачем это нужно
- Защита от каскадных отказов Если один вызов упал из-за rate limit, повторные вызовы только усугубят ситуацию (получат ещё больше 429). Circuit breaker быстро останавливает поток запросов.
- Экономия токенов и денег В открытом состоянии запросы не выполняются, не тратятся лимиты и бюджет.
- Улучшение пользовательского опыта Вместо долгого ожидания таймаута пользователь получает мгновенный fallback (например, «Сервис временно недоступен, попробуйте позже» или кэшированный ответ).
4.2 Какие ошибки отслеживать
- HTTP 429 (Too Many Requests) — превышение rate limit.
- HTTP 500, 502, 503, 504 — серверные ошибки.
- Timeout — превышение времени ожидания ответа (например, >30 секунд).
- Network errors — сбой соединения (DNS, TLS).
4.3 Fallback стратегии для LLM
- Кэш Вернуть ранее сгенерированный ответ на похожий запрос (если применимо).
- Заглушка «Извините, сервис временно недоступен».
- Альтернативная модель Переключиться на другого провайдера (например, с GPT-4 на GPT-3.5 или на локальную модель).
- Очередь Поставить запрос в очередь и обработать позже (асинхронный fallback).
5. Реализации circuit breaker
5.1 Библиотеки для Python
- pybreaker — простая реализация с поддержкой декораторов.
- tenacity — библиотека для retry, но может использоваться как основа для circuit breaker.
- aiobreaker — асинхронная версия для asyncio.
- resilience4j (Java) — популярная библиотека, портирована на Python в виде
resilience4py.
5.2 Инфраструктурные решения
- Istio — service mesh, который может реализовать circuit breaker на уровне прокси (Envoy). Настраивается через
DestinationRule. - Envoy proxy — встроенная поддержка circuit breaker (max connections, max pending requests, max requests, max retries).
- AWS App Mesh — аналогично.
5.3 Пример на Python с pybreaker
import pybreaker
import requests
from functools import wraps
# Создаём circuit breaker с параметрами
breaker = pybreaker.CircuitBreaker(
fail_max=5, # 5 ошибок подряд
reset_timeout=30, # 30 секунд до half-open
exclude=[requests.HTTPError] # можно исключить некоторые ошибки
)
def call_llm_api(prompt: str) -> str:
"""Функция вызова LLM API, обёрнутая circuit breaker."""
@breaker
def _call():
response = requests.post(
"https://api.openai.com/v1/chat/completions",
json={"model": "gpt-4", "messages": [{"role": "user", "content": prompt}]},
timeout=30
)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
try:
return _call()
except pybreaker.CircuitBreakerError:
# Fallback: вернуть кэш или заглушку
return "Сервис временно недоступен. Попробуйте позже."
# Использование
result = call_llm_api("Расскажи о circuit breaker")
5.4 Пример с tenacity (кастомный circuit breaker)
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import requests
# Tenacity не имеет встроенного circuit breaker, но можно эмулировать через retry + стоп-условия
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10),
retry=retry_if_exception_type((requests.exceptions.Timeout, requests.exceptions.HTTPError))
)
def call_llm_with_retry(prompt: str) -> str:
response = requests.post(
"https://api.openai.com/v1/chat/completions",
json={"model": "gpt-4", "messages": [{"role": "user", "content": prompt}]},
timeout=30
)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
Замечание Tenacity не реализует half-open и fallback, поэтому для полноценного circuit breaker лучше использовать pybreaker или resilience4py.
6. Метрики и мониторинг circuit breaker
Для эффективного использования circuit breaker необходимо отслеживать:
| Метрика | Описание | Инструмент |
|---|---|---|
| State | Текущее состояние (closed/open/half-open) | Prometheus Gauge |
| Failure count | Количество ошибок за окно | Counter |
| Success count | Количество успешных вызовов | Counter |
| Fallback count | Сколько раз использован fallback | Counter |
| Latency | Время ответа (успешных и неуспешных) | Histogram |
Пример экспорта метрик в Prometheus (с pybreaker):
from prometheus_client import Counter, Gauge
state_gauge = Gauge('circuit_breaker_state', '0=closed,1=open,2=half-open', ['api'])
fallback_counter = Counter('circuit_breaker_fallback_total', 'Number of fallbacks', ['api'])
# В коде обновлять метрики при изменении состояния
7. Связь circuit breaker с другими паттернами отказоустойчивости
| Паттерн | Роль | Взаимодействие с circuit breaker |
|---|---|---|
| Retry | Повтор неудачных вызовов с задержкой | Retry применяется до circuit breaker. Если retry исчерпан, ошибка передаётся circuit breaker. |
| Bulkhead | Изоляция ресурсов (пулы потоков) | Bulkhead ограничивает количество параллельных вызовов к API, circuit breaker защищает от лавины ошибок. |
| Timeout | Ограничение времени ожидания | Таймаут — один из источников ошибок для circuit breaker. |
| Rate Limiter | Ограничение частоты запросов | Rate limiter предотвращает 429, circuit breaker реагирует на них. |
| Fallback | Альтернативное действие | Fallback — неотъемлемая часть circuit breaker в открытом состоянии. |
8. Плюсы и минусы circuit breaker для LLM API
Плюсы
- Предотвращение каскадных отказов — защита как клиента, так и сервера.
- Быстрый отказ (fail-fast) — пользователь не ждёт таймаута.
- Автоматическое восстановление — half-open проверяет готовность сервиса.
- Экономия ресурсов — не тратятся токены и деньги на бесполезные запросы.
Минусы
- Дополнительная сложность — нужно настраивать пороги и fallback.
- Ложные срабатывания — если порог слишком низкий, цепь может размыкаться при временных сбоях.
- Необходимость мониторинга — без метрик трудно понять, почему падают ответы.
- Задержка при half-open — пробные запросы могут всё ещё падать, увеличивая время восстановления.
9. Пет-проект для закрепления
Задача Реализовать микросервис на FastAPI, который вызывает OpenAI API через circuit breaker с fallback на локальную модель (например, через Ollama).
Инструменты
- Python, FastAPI, pybreaker, requests, prometheus_client, Docker (опционально).
- OpenAI API (или эмуляция с помощью
responsesбиблиотеки). - Локальная LLM через Ollama (например, llama3).
Шаги:
- Создать FastAPI endpoint
/generateс параметромprompt. - Настроить circuit breaker с порогом 3 ошибки за 30 секунд, reset timeout 60 секунд.
- В нормальном состоянии вызывать OpenAI API.
- При размыкании цепи возвращать ответ от локальной модели (Ollama).
- Экспортировать метрики состояния и количества fallback в Prometheus.
- Написать тесты: симулировать ошибки API (через mock) и проверить переключение на fallback.
Ожидаемый результат
- При работающем OpenAI — ответы от GPT.
- При имитации сбоя (например, возврат 503) — после 3 ошибок все запросы идут в Ollama.
- После восстановления API — circuit breaker автоматически возвращается к OpenAI.
10. Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 236 | Что такое retry стратегии и exponential backoff? |
| 238 | Как реализовать bulkhead для LLM вызовов? |
| 239 | Какие метрики отказоустойчивости нужно отслеживать? |
| 240 | Как организовать fallback между разными LLM провайдерами? |
| 241 | Что такое rate limiting и как его настроить для API? |
11. Навигация
- Предыдущий: 236
- Следующий: 238
- Индекс: 00. Индекс разборов
Навигация
- Предыдущий: 236
- Следующий: 238
- Индекс: 00. Индекс разборов