Операції та Управління → Залежності сервісів
Залежності сервісів
1) Навіщо це потрібно
Будь-яка продакшн-платформа - це граф: користувачі → Edge/API → доменні сервіси → черги/стріми → БД/кеші → зовнішні провайдери (платежі, KYC, провайдери ігор). Помилка на одному ребрі графа часто «гуляє» по всій мережі: ростуть затримки, спрацьовують ретраї, забиваються черги, відбуваються каскадні відмови. Управління залежностями знижує «вибуховий радіус» і робить релізи передбачуваними.
Цілі:- Бачити повний граф викликів і розуміти, хто від кого залежить.
- Запобігати каскадні відмови і «шторм ретраїв».
- Планувати релізи з урахуванням сумісності та SLO-пропагандації.
- Підвищувати MTTR: швидше знаходити справжній першопричинний вузол (root cause).
2) Типи залежностей
Синхронні (RPC: REST/gRPC/GraphQL): жорстка зв'язність по латентності/доступності. Потрібні таймаути, брейкери, бюджет ретраїв.
Асинхронні (Event/Stream: Kafka/Rabbit/Pulsar): більш стійка зв'язність, але є lag/backlog і семантика доставки (at-least-once, idempotency).
Сховища (DB/Cache/Object store): ресурси → контеншн, ліміти конектів/IOPS, eviction, реплікація.
Зовнішні провайдери (PSP/KYC/ігрові провайдери): квоти, платні виклики, вікна обслуговування, юридичні SLA.
Операційні (релізи, фічефлаги, конфіги): непрямі залежності через налаштування, секрети, schema registry.
3) Каталог сервісів і граф залежностей
Що фіксуємо в каталозі (Backstage/Service Catalog/CMDB):- Власники (Squad/чат/On-call rota), репо, середовище, артефакти.
- Контракти API (OpenAPI/AsyncAPI), версії, сумісність (back/forward).
- Вхідні/вихідні залежності (upstream/downstream) з типом (sync/async), критичність, очікування SLO.
- Бюджет таймаутів/ретраїв, брейкери, bulkhead-пули.
- Дані про квоти та ліміти зовнішніх інтеграцій.
- `service: payments-api`
- Upstream: `user-profile` (sync), `risk-score` (async).
- Downstream: 'PSP-X'( sync, квота 2k RPS),'ledger'( async).
- SLO: p99 ≤ 300 мс, 99. 9% uptime.
- Таймаути: 200 мс до «PSP-X», 150 мс до «user-profile».
- Ретраї: 2 з експоненціальною затримкою, джиттер.
- Брейкер: open на 30 с при 5% помилок/10 с.
4) SLO-пропагандація і «бюджет латентності»
При ланцюжку синхронних викликів підсумковий SLO формується з суми затримок і ймовірностей відмов.
Принципи:- Бюджет запиту розбивається зверху вниз: фронтовий SLO 500 мс → Edge 50 мс → API 150 мс → доменні сервіси 200 мс → провайдер 100 мс.
- Таймаути «назовні коротше, ніж всередину»: у викликає таймаут менше сумарного внутрішнього, щоб оновлювалися ресурси, а не накопичувалися зомбі-виклики.
- Ретраї тільки на безпечні коди/винятки і з джиттером; без ретраїв на таймаути вузьких місць (інакше «шторм»).
5) Контракти та сумісність
Версіонування API: SemVer для контрактів; backward-compatible зміни через поля «optional», розширення схеми; видалення - тільки через «депрекейт-період».
Consumer-driven contracts (CDC): тести споживачів (Pact-подібні) запускаються проти провайдера в CI; реліз блокується при несумісності.
Схема-регістри (Async): версія топіків/подій, еволюція схем (Avro/JSON-Schema), політика «can-read-old/can-write-new».
6) Інженерні патерни стійкості
Timeouts: відокремлюємо SLA бізнесу від технічних очікувань; кожне вихідне з'єднання - явний таймаут.
Retries + backoff + jitter: не більше 2-3 спроб, враховуючи ідемпотентність.
Circuit Breaker: «швидке падіння» при деградації даунстріму; half-open проби.
Bulkhead (ізоляція пулів): для різних даунстрімів - окремі пули потоків/подів/з'єднань.
Rate-limit/Leaky-bucket: щоб не вбивати даунстріми при піках.
Idempotency & дедуплікація: ключ ідемпотентності на рівні запиту/повідомлення; дід-лейтери і ретрай-черги.
Кешування та фоллбеки: локальні/розподілені кеші, статуси «stale-while-revalidate», деградація контенту.
outbound:
psp-x:
timeout_ms: 200 retries: 2 retry_on: [5xx, connect_error]
backoff: exponential jitter: true circuit_breaker:
error_rate_threshold: 0. 05 window_s: 10 open_s: 30 pool: dedicated-psp (max_conns: 200)
7) Спостережуваність залежностей
Розподілені трасування (TraceID, Baggage): бачити шлях запиту по ланках; спані на вихідні виклики з тегами'peer. service`, `retry`, `timeout`.
Метрики per-dependency: `outbound_latency_p99`, `outbound_error_rate`, `open_circuit`, `retry_count`, `queue_lag`.
- Карта сервісів з колірною індикацією SLO і помилкових ребер.
- «Top N проблемних залежностей» за останній тиждень.
- «Blast radius» - список сервісів, які постраждають при падінні X.
- Логи кореляції: включати'trace _ id '/' span _ id'в журнали.
8) Управління релізами з урахуванням залежностей
Dependency-aware пайплайни: реліз провайдера блокується, якщо CDC-тести споживачів червоні.
Поступове включення (фічефлаги): нові поля/ендоінти → для 1% споживачів → 10% → 100%.
Канарські релізи: перевіряємо ключові залежності і «бюджет латентності» на частці трафіку.
Сумісність схем: продюсер пише'vNew', консюмери читають'vOld/vNew'; після переходу - «збір сміття» старих полів.
9) Інциденти та ескалації по графу
Визначаємо «істинного винуватця»: alert-кореляція - якщо деградував'PSP-X', не пейджим весь «платіжний кущ», а власника інтеграції.
Автодеградація: фічефлаг «мінімальний режим» (менш важкі ендпоінти, урізані бандли, відключення не-критичних фіч).
Гарди від каскадів: обмежуємо паралелізм, вимикаємо ретраї на гарячій гілці, відкриваємо брейкер заздалегідь (pre-open).
- Діагностика: які дашборди/метрики, як перевірити квоти/ліміти.
- Дії: знизити RPS, перемкнути на резервного провайдера, тимчасово включити кеш-відповіді.
- Відкат і валідація: повернути параметри, переконатися в нормі p95/p99 і error-rate.
10) Матриця критичності залежностей
Оцініть кожен зв'язок по осях: Правила:- Для «критичних» - подвійний провайдинг, брейкери, окремі пули, хаос-тести.
- Для «високих» - хоча б деградація і «зелена кнопка» вимкнення фічі.
- Для «середніх/низьких» - ліміти на ретраї та бюджет черг.
11) Процес: від інвентаризації до експлуатації
1. Картування графа: зібрати фактичні виклики (трасування) + декларативні залежності з каталогу.
2. Призначити власників: на кожен сервіс і зовнішню інтеграцію - відповідальний on-call.
3. Визначити SLO і бюджети: латентність/помилки, таймаути/ретраї/пули.
4. Формалізувати контракти: OpenAPI/AsyncAPI, схеми і CDC.
5. Включити патерни стійкості: timeouts/retries/circuit/bulkhead.
6. Налаштувати дашборди та алерти per-dependency.
7. Поставити реліз-гейти: блок по CDC/сумісності/канарці.
8. Регулярні game-days: хаос-експерименти по падінню ключових ребер.
9. Постмортеми з фокусом на зв'язку: що посилило каскад, як звузити радіус.
12) Алерти на залежності (ідеї правил)
Синхронні даунстрими:- `outbound_error_rate{to="X"} > 3% FOR 10m` → warning; `>5% FOR 5m` → critical.
- `outbound_p99_latency{to="X"} > SLO1. 3 FOR 10m` → warning.
- ' circuit _ open {to =» X»} = = 1 FOR 1m'→ page власнику інтеграції.
- ' retry _ rate {to =» X»}> baseline2 FOR 5m'+'outbound _ rps> 0'→ ризик шторму.
- `consumer_lag{topic="Y"} growth > threshold FOR 10m` + `hpa at max` → крит.
- ' usage _ quota {provider =» PSP-X «}> 90% window'→ попередження, автопереключення маршрутів.
13) Анти-патерни
«Один загальний пул потоків на всі даунстрими». Разом: head-of-line blocking. Діліть пули.
Без таймаутів/з нескінченними ретраями. Так народжується шторм.
Сліпі ретраї неідемпотентних операцій. Дублі списань/ставок.
Прихована «загальна БД» як точка зв'язності. Сильна конкуренція і блокування.
Версія API змінюється без CDC і депрекейт-плану. Ловіть масові падіння.
Спостережуваність тільки по сервісах, не по зв'язках. Не видно, де рветься ланцюг.
14) Дашборди: Мінімальний набір
Service Map: інтерактивна карта сервісів з метриками ребер (latency/error/volume).
Upstream/Downstream Overview: для власника сервісу - вхідні залежності (хто дзвонить), вихідні (кому телефонуємо), «топ проблем».
Dependency Drilldown: картка конкретного зв'язку: p50/p95/p99, помилки по класах, відсоток відкритого брейкера, ретраї, пул з'єднань, квоти/кост.
Release Context: анотації релізів/фічефлагів на графіках залежностей.
15) Чек-лист впровадження
- Каталог сервісів з власниками та контрактами (OpenAPI/AsyncAPI).
- Повний граф залежностей з трасувань (оновлювати щодня).
- SLO по сервісу і «бюджети латентності» вниз по ланцюжку.
- Явні таймаути, ретраї з джиттером, брейкери, bulkhead-ізоляція.
- CDC-тести в CI як реліз-гейт.
- Дашборди per-dependency і карта сервісу.
- Алерти на ребрах + suppression по першопричині.
- Game-days: падіння провайдера/кластера/топіка і перевірка деградацій.
- План деградації: які фічі відключаємо, які кеші включаємо.
- Регулярні постмортеми з діями по зменшенню зв'язності.
16) KPI якості управління залежностями
Dependency MTTR: медіана відновлення по ребру.
Blast Radius Index: середнє число порушених сервісів при падінні одного.
Coupling Score: частка sync-залежностей серед усіх; тренд до зниження.
CDC Pass Rate: % релізів без порушень контрактів.
Retry Storms/місяць: цільове значення → 0.
Cost of External Calls: вартість зовнішніх викликів на 1k RPS (бачити ефект кешування/фоллбеків).
17) Швидкий старт (дефолти)
Таймаути: 70-80% від бюджету ланки; верхній таймаут запиту <сума внутрішніх.
Ретраї: max 2, тільки на ідемпотентні 5хх/мережеві, з backoff + джиттер.
Брейкер: поріг 5% помилок за 10 с, open = 30 с, half-open пробами.
Bulkhead: виділені пули/ліміти сполук на кожного даунстріму.
CDC: обов'язкові для всіх публічних API і топіків.
Async-преференс: де можна - перехід на події/черги (розв'язка за часом).
18) FAQ
Q: Що важливіше: ретраї або брейкер?
A: Обидва. Ретраї рятують від короткочасних збоїв, брейкер захищає від перманентної деградації і штормів.
Q: Як зрозуміти, що зв'язок «занадто крихкий»?
A: Висока кореляція помилок, низький запас таймаутів, часті ретраї, відсутність фоллбеків/кешів, синхронні довгі ланцюжки.
Q: Навіщо CDC, якщо у нас інтеграційні тести?
A: CDC фіксує очікування споживача і ламає реліз провайдера при несумісності - раніше, ніж код потрапить в прод.