Граціозна деградація
1) Суть підходу
Граціозна деградація - це керований перехід системи в більш простий, але корисний режим при нестачі ресурсів, збої залежностей або піках навантаження. Мета - зберегти ядро цінності для користувача і стійкість платформи, пожертвувавши другорядними можливостями і якістю.
Ключові властивості:- Передбачуваність: заздалегідь визначені сценарії і «сходи» деградації.
- Обмеження радіусу ураження: ізоляція фіч і залежностей.
- Спостережуваність: метрики, логи і трасування «який рівень деградації активний і чому».
- Оборотність: швидке повернення до норми.
2) Принципи і межі
1. Зберегти головне: свій основний SLA/SLO (наприклад, «покупка», «логін», «пошук») - пріоритет вище другорядних (аватари, рекомендації, анімації).
2. Fail-open vs fail-closed:- Безпека, платежі, права - fail-closed (краще відмова, ніж порушення).
- Кешований контент, підказки, аватари - fail-open з фолбеком.
- 3. Тимчасові бюджети: таймаути зверху вниз (клієнт <шлюз <сервіс). Після закінчення - деградація замість ретраїв до нескінченності.
- 4. Контроль вартості: деградація повинна знижувати споживання CPU/IO/мережі, а не просто «ховати» помилки.
3) Рівні деградації
3. 1 Клієнт/UX
Skeletons/плейсхолдери і «ледача» підвантаження другорядних віджетів.
Partial UI: критичні блоки вантажаться, вторинні - ховаються/спрощуються.
Кеш на стороні клієнта: last-known-good (LKG) з позначкою «дані могли застаріти».
Офлайн-режим: черга команд з повтором пізніше (ідемпотентність!).
3. 2 Edge/CDN/WAF/API-шлюз
stale-while-revalidate: віддаємо кеш, фоном оновлюємо.
Rate limiting & load shedding: при перевантаженні скидаємо фоновий/анонімний трафік.
Geofence/зважений роутинг: трафік відводиться в найближчий здоровий регіон.
3. 3 Сервісний шар
Partial response: повертаємо частину даних +'warnings'.
Read-only режим: тимчасова заборона мутацій (прапори).
Brownout: тимчасове відключення ресурсомістких фіч (рекомендації, збагачення).
Adaptive concurrency: динамічно зменшуємо паралелізм.
3. 4 Дані/стрімінг
Кеш як джерело істини з TTL (тимчасово): «краще приблизно, ніж ніяк».
Знижена точність моделей/алгоритмів (fast path vs accurate path).
Defer/queue: перенесення важких завдань у фон (outbox/job queue).
Пріоритетні черги: критичні події - в окремому класі.
4) «Сходи» деградації (playbooks)
Приклад для пошукового API:- L0 (норма) → L1: приховати персоналізацію і банери → L2: відключити синоніми/фаззі-пошук → L3: лімітувати розмір відповіді і таймаут до 300 мс → L4: віддавати результати з кешу 5 хв → L5: «read-only & cached only» + черга запитів на перерахунок.
- Тригери: перевантаження CPU> 85% р95> цільового, помилки> порогу, лаг Kafka> порогу, флап залежностей.
- Дії: включити прапор X, знизити concurrency до N, перемкнути джерело Y на кеш.
- Критерії виходу: 10 хвилин зелених метрик, запас по ресурсах.
5) Політики прийняття рішень
5. 1 Помилковий бюджет і SLO
Використовуйте error-budget burn rate як тригер brownout/шеддингу.
Політика: «якщо burn-rate> 4 × протягом 15 хв - включити L2 деградації».
5. 2 Admission control
Обмежуємо вхідний RPS на критичних шляхах, щоб гарантувати p99 і не допустити колапсу черг.
5. 3 Пріоритизація
Класи: interactive > system > background.
Пер-тенант пріоритети (Gold/Silver/Bronze) і справедливість (fair share).
6) Патерни та реалізації
6. 1 Load shedding (серверний)
Скидайте запити до того, як вони займуть всі ресурси.
Повертайте'429 '/' 503'з'Retry-After'і поясненням політики (для клієнтів).
Envoy (adaptive concurrency + circuit breaking)
yaml typed_extension_protocol_options:
envoy. filters. http. adaptive_concurrency:
"@type": type. googleapis. com/envoy. extensions. filters. http. adaptive_concurrency. v3. AdaptiveConcurrency gradient_controller_config:
sample_aggregate_percentile: 90 circuit_breakers:
thresholds:
- max_requests: 2000 max_pending_requests: 500 max_connections: 1000
6. 2 Brownout (тимчасове спрощення)
Ідея: знижувати «яскравість» (вартість) фіч, коли ресурси закінчуються.
kotlin class Brownout(val level: Int) { // 0..3 fun recommendationsEnabled() = level < 2 fun imagesQuality() = if (level >= 2) "low" else "high"
fun timeoutMs() = if (level >= 1) 150 else 300
}
6. 3 Partial response і попередження
Поле'warnings '/' degradation'у відповіді:json
{
"items": [...],
"degradation": {
"level": 2,
"applied": ["cache_only", "no_personalization"],
"expiresAt": "2025-10-31T14:20:00Z"
}
}
6. 4 Stale-while-revalidate на краю (Nginx)
nginx proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout http_500 http_502 http_504 updating;
proxy_cache_background_update on;
6. 5 Read-only перемикач (Kubernetes + прапор)
yaml apiVersion: v1 kind: ConfigMap data:
MODE: "read_only"
The code should check MODE and block mutations with a friendly message.
6. 6 Kafka: backpressure і класи черг
Перемкніть heavy-консюмерів в менший'max. poll. records', обмежте продюсерські batch-і.
Розділіть «критичні» і «bulk» події по топіках/квотах.
6. 7 UI: graceful fallback
Ховайте «важкі» віджети, показуйте кеш/скелетон і чітко маркуйте застарілі дані.
7) Конфігураційні приклади
7. 1 Istio: outlier + пули пріоритету
yaml outlierDetection:
consecutive5xx: 5 interval: 10s baseEjectionTime: 30s maxEjectionPercent: 50
7. 2 Nginx: фоновий трафік під ніж першим
nginx map $http_x_priority $bucket { default low; high high; }
limit_req_zone $binary_remote_addr zone=perip:10m rate=20r/s;
limit_req_status 429;
server {
location /api/critical/ { limit_req zone=perip burst=40 nodelay; }
location /api/background/ {
limit_req zone = perip burst = 5 nodelay; # stricter
}
}
7. 3 Feature flags / kill-switches
Зберігайте в динамічній конфігурації (ConfigMap/Consul), оновлення без релізу.
Розділяйте пер-фічу і глобальні прапори, логуйте активації.
8) Спостережуваність
8. 1 Метрики
'degradation _ level {service}'- поточний рівень.
'shed _ requests _ total {route, reason}'- скільки скинуто і чому.
'stale _ responses _ total'- скільки видано кешу.
`read_only_mode_seconds_total`.
`brownout_activations_total{feature}`.
Помилковий бюджет: burn-rate, частка порушень SLO.
8. 2 Трейсинг
Атрибути спанів: `degraded=true`, `level=2`, `reason=upstream_timeout`.
Лінки між ретраями/hedged-запитами, щоб бачити внесок у хвости.
8. 3 Логи/алерти
Події перемикань рівнів деградації з причинами і власником зміни.
Алерти на «залипання» рівня (деградація тримається занадто довго).
9) Управління ризиками та безпека
Не деградуйте автентифікацію/авторизацію/цілісність даних: краще відмова.
Маскування PII зберігається в будь-яких режимах.
Фінанси/платежі: тільки ідемпотентні операції, строгі таймаути і відкати; при сумнівах - read-only/hold.
10) Анти-патерни
Тиха деградація без підказки користувачеві і без телеметрії.
Ретрай-шторми замість load shedding і коротких таймаутів.
Глобальні «рубильники» без сегментації - величезний blast radius.
Змішування prod і «полегшених» шляхів в одному кеші/черзі.
Вічна деградація: brownout як «нова норма», забуті критерії виходу.
Stale-write: спроби записувати на основі застарілих даних.
11) Чек-лист впровадження
- Визначені ядро цінності і критичні призначені для користувача сценарії.
- Складені сходи деградації по сервісах/домейнах з тригерами і виходами.
- Введені таймаути/обмеження і server-side load shedding.
- Налаштовані rate limits і пріоритетні класи трафіку.
- Реалізовані partial response, read-only, stale-while-revalidate.
- Інтегровані feature flags/kill-switches з аудитом.
- Метрики/трейсинг/алерти для рівнів деградації і причин.
- Регулярні game day навчання з симуляцією перевантаження/збоїв.
- Документовані SLO і політика error-budget → деградація.
12) FAQ
Q: Коли вибирати brownout, а коли - shedding?
A: Якщо мета - знизити вартість запитів без відмов - brownout. Якщо мета - захистити систему, коли навіть спрощення не допомагає - shedding входу.
Q: Чи повідомляти користувачеві про деградацію?
A: Для критичних сценаріїв - так (бейдж «обмежений режим»). Прозорість знижує підтримку і невдоволення.
Q: Чи можна кеш зробити джерелом істини?
A: Тимчасово - так, при явних SLA і мітках застарівання. Для мутацій - заборонено.
Q: Як не «зламаними» зробити ретраї?
A: Короткі таймаути, експоненціальний backoff з джиттером, ідемпотентність і ліміт спроб; ретраїть тільки безпечні операції.
13) Підсумки
Граціозна деградація - це архітектурний контракт і набір керованих режимів роботи, що включаються за сигналами метрик і помилкового бюджету. Правильно спроектовані сходи, строгі таймаути і шеддинг, кеш-фолбеки і brownout, плюс потужна спостережуваність - і ваша платформа залишається корисною і економною навіть в шторм.