Resilience Patterns
Resilience — не магия, а набор явных правил: circuit breaker, retry with backoff + jitter, timeout cascade, bulkhead-изоляция, graceful degradation, idempotency. Каждое из этих правил легко описывается, но я регулярно вижу команды, которые знают слова, но не реализуют дисциплинированно: retry без jitter (thundering herd при первом downtime), circuit breaker без recovery strategy («открылся навсегда»), idempotency «допилим потом» (а deploy уже завтра). Лист — про дисциплину применения. Соседний лист к Capacity Planning и SLO Engineering под L1 Reliability Engineering. Граница: capacity planning — готовимся к нагрузке; resilience patterns — выживаем, когда подготовка не сработала.
Что должен уметь
Заголовок раздела «Что должен уметь»Главный навык на уровне L4 — реализовать exponential backoff + jitter правильно. Я регулярно вижу команды, которые написали retry «с backoff», но не добавили jitter — и при первом downtime получили retry-storm, добивший downstream. Marc Brooker написал лучший разбор (AWS Architecture Blog 2015) — full jitter vs equal jitter vs decorrelated jitter с симуляциями. Это материал на час чтения и год пользы.
L3
- Знает базовый набор паттернов (circuit breaker, retry, timeout, fallback); применяет их через библиотеки своего стека (Polly / resilience4j / Tenacity / retry-axios), не изобретая велосипед.
- Понимает разницу между liveness и readiness probes; пишет адекватные health checks (shallow «процесс жив» vs deep «зависимости доступны»).
L4
- Реализует retry с exponential backoff + jitter; знает, почему «retry без jitter = thundering herd» и почему «infinite retry без circuit breaker = retry amplification cascade».
- Управляет timeouts иерархически: cascading timeouts (внутренний < внешнего с запасом на retry), отказ от bare network defaults, deadline propagation между микросервисами.
L5
- Проектирует bulkhead-изоляцию: connection pools / thread pools / queue partitions, чтобы перегрузка одной зависимости не съедала ресурсы остальных.
- Реализует graceful degradation с явными criticality levels: feature flags для отключения некритичных функций, fallback responses, кешированные данные. Degraded mode описан и тестируется в game day.
- Делает idempotency requirement для всех retry-safe операций: idempotency keys, ETags, conditional writes, transaction outbox.
L6+
- Проектирует load shedding и backpressure: criticality-based prioritization, drop low-criticality traffic при overload, queue-depth-based admission control, retry budget на уровне сервиса.
- Внедряет chaos engineering как практику проверки resilience patterns в действии.
Материалы
Заголовок раздела «Материалы»- Michael Nygard — Release It! Design and Deploy Production-Ready Software (Pragmatic Bookshelf, 2-е изд., 2018). Каноническая книга по resilience: глава 5 «Stability Patterns» (circuit breaker, bulkhead, steady state, fail fast), глава 4 «Stability Antipatterns». После 20 лет — всё ещё лучший single-source.
- Cindy Sridharan — Distributed Systems Observability (O’Reilly, 2018). Связь resilience patterns и observability: как увидеть, что circuit breaker открыт, как поймать retry storm в метриках.
Статьи и доклады
Заголовок раздела «Статьи и доклады»- Addressing Cascading Failures — SRE Book гл. 22. Канонический разбор: причины cascading failure, retry amplification, server overload, query-of-death.
- Handling Overload — SRE Book гл. 21. Дополняет: client-side throttling, criticality levels, retry budgets, deadlines (deadline propagation в RPC).
- Marc Brooker — Exponential Backoff and Jitter (AWS Architecture Blog, 2015). Главный публичный кейс — см. ниже.
- Netflix Tech Blog — Making the Netflix API more resilient. История появления Hystrix и обоснование bulkhead patterns на реальной системе.
Инструменты
Заголовок раздела «Инструменты»- resilience4j (Java) — современная замена Hystrix. Circuit breaker, retry, rate limiter, bulkhead, timeout как composable модули, не монолит. По моим наблюдениям, чаще выбирают именно её для нового Java-кода.
- Polly (.NET) — каноническая resilience library. Fluent API, те же patterns.
- Tenacity (Python) — простая retry library с обширной конфигурацией backoff / jitter / stop conditions. Если кроме retry больше ничего не нужно — её достаточно.
- Envoy / Istio circuit breaking — service mesh уровень: circuit breaking, outlier detection, retries на уровне sidecar без изменения кода. Подходит, когда сервис нельзя менять или язык не имеет хорошей resilience-библиотеки.
- Chaos Mesh / Litmus / AWS Fault Injection Service — chaos engineering tools для проверки resilience patterns в действии.
Best practices
Заголовок раздела «Best practices»Главный публичный кейс на тему backoff — Marc Brooker, «Exponential Backoff and Jitter» (AWS Architecture Blog, 2015). В статье симуляциями показано: при общем downtime downstream клиенты с linear retry бьются синхронно одной волной (thundering herd), и downstream не успевает восстановиться. Equal jitter (random между half и full backoff) распределяет нагрузку. Для AWS-style клиентов decorrelated jitter ещё лучше — приведена формула и графики. Если кто-то в команде написал retry без jitter — отправляйте на эту статью первым делом. Один час чтения, который окупается за первый же downtime.
Короткие правила:
- Retry только на idempotent операциях; идемпотентность — пре-условие, а не «допилим потом». Каждый retry без idempotency key — потенциальный double-write / double-charge. Idempotency либо в API контракте, либо retry отключён. Idempotency keys + dedup window — типовая реализация.
- Exponential backoff + jitter — обязательны; linear retry даёт thundering herd. «Retry 5 раз с интервалом 1s» при сбое downstream — все клиенты бьются синхронно. Equal jitter распределяет нагрузку, decorrelated jitter — ещё лучше.
- Health check ≠ business logic check. Liveness probe лезет в DB и возвращает fail при DB outage → k8s перезапускает все pods → каскад. Liveness отвечает «процесс жив?»; readiness — «готов принимать traffic?». DB outage отключает readiness, но не liveness.
Подробнее:
Circuit breaker без явной recovery strategy = «открылся навсегда». Написали open → half-open → close, не подумали, что должно произойти для перехода. Recovery: после cooldown пропустить 1 пробный запрос; успех → close, fail → обратно в open с увеличенным cooldown. Метрики circuit state — обязательны в дашборде сервиса; без visibility непонятно, когда CB активен.
Timeouts cascade: внутренний < внешнего с запасом на retry. Внешний клиент timeout 30s, internal RPC timeout тоже 30s — внутренний всегда «успевает» по своему таймеру, но клиент уже отвалился. Каждый уровень должен timeout раньше родителя на retry-budget + safety margin. Deadline propagation (передача remaining time через gRPC headers / Twirp metadata) — продвинутый уровень, но решает целую категорию проблем cascade.
Graceful degradation требует явных criticality levels. «При overload отключим что-нибудь» — без классификации сервисов / запросов на critical / important / shedable невозможно решать, что shed. SRE Book вводит criticality model — critical / shedable+ / shedable. Признак зрелого сервиса: degraded mode явно описан и регулярно тестируется (game day). По моим наблюдениям, без criticality labels graceful degradation существует только на бумаге.
Resilience patterns без observability — слепое пятно. Добавили circuit breaker и retry, но не выводим метрики «retry rate», «circuit state», «shed rate» — в инциденте не видно, активны ли patterns; на ревью неясно, помогают они или маскируют проблему. Каждый pattern — отдельный SLI и dashboard panel. Это базовая дисциплина, которую часто откладывают.
Связанные листья
Заголовок раздела «Связанные листья»- Capacity Planning — resilience patterns закрывают ситуацию, когда capacity исчерпан или forecast ошибся. Graceful degradation + load shedding — что делается, пока scaling догоняет (если догонит).
- SLO Engineering — patterns поддерживают SLO под нагрузкой и при отказах. Circuit breaker не даёт error budget сгореть на cascade-фейлах.
- Networking — timeouts, retry, circuit breaker патчат network unreliability. Service mesh реализует часть patterns на инфра-слое.
- SLI-based Alerting — алерты ловят момент активации patterns (circuit open, retry rate up, shed rate ≠ 0).
- Chaos Engineering — chaos валидирует patterns: circuit breaker реально открывается? retry с backoff не амплифицирует? bulkhead изолирует?
- Progressive Delivery — canary с health gate использует readiness probes и circuit-breaker метрики.
- Operating Systems — OS-level health (open file descriptors, conntrack, page cache pressure) — то, на что часто реагирует graceful degradation; resilience pattern triggers — kernel signals.
- Service Mesh — Envoy/Istio sidecar реализует circuit breaking / outlier detection / retry policies без изменения кода; mesh — одна из инфра-реализаций паттернов из этого листа.
- Containerization & Orchestration — PDB / HPA / topology spread / liveness-readiness probes — k8s-native реализации resilience patterns.
Открытые вопросы
Заголовок раздела «Открытые вопросы»- Idempotency Patterns (TBD) — отдельный лист: idempotency keys, ETags, conditional writes, transaction outbox, exactly-once illusion.
- Backpressure & Load Shedding (TBD) — «downstream direction» graceful degradation: criticality classification, admission control, queue management, retry budgets.
- Resilience SLIs — какой SLI выбрать для самих patterns (circuit-open ratio, retry success rate, shed rate)?