Shadow-трафік і порівняння
1) Що таке Shadow-трафік і навіщо він потрібен
Shadow-трафік (він же traffic mirroring/dark launch) - це безпечна «прогонка» реальних запитів/подій на нову версію сервісу паралельно з продакшн-версією без впливу на користувачів. Результати нової версії не повертаються клієнту і не виробляють зовнішніх сайд-ефектів, а збираються в систему порівняння.
Ключові цілі:- Перевірка сумісності: схем, контрактів, бізнес-логіки.
- Оцінка продуктивності: латентність, стійкість під реальним навантаженням.
- Детекція дрейфу: відмінності у відповідях, розподілах, частоті помилок.
- Підготовка до канареечних релізів: зниження ризику перед реальним перемиканням трафіку.
- Переписування ядра/алгоритмів, міграції БД/кешів, перехід на інший рантайм/SDK, зміна провайдера зовнішнього API.
2) Архітектурні патерни Shadow-трафіку
2. 1 L7-проксі/шлюз (HTTP/gRPC)
Проксі приймає запит → віддає бойову відповідь зі старої версії → асинхронно дзеркалює копію запиту в «тінь».
Підходить для синхронних API.
Управління часткою/фільтром дзеркалювання: по дорозі, хедеру, користувачеві, тенанту.
yaml route:
route:
cluster: prod-v1 request_mirror_policies:
- cluster: shadow-v2 runtime_fraction:
default_value:
numerator: 10 # 10% denominator: HUNDRED trace_sampled: true
Приклад (Nginx):
nginx location /api/ {
proxy_pass http://prod_v1;
mirror/shadow; # request copy
}
location = /shadow {
internal;
proxy_pass http://shadow_v2; # answer ignored
}
2. 2 Шини подій (Kafka/Потоки)
На рівні топіка робиться tee:- Продюсер пише як зазвичай → консюмери prod читають.
- Паралельно «тінь» (shadow-pipeline) читає той же потік в окрему пісочницю.
Параметри: MirrorMaker/Replicator, dual-write (обережно), бриджі «source → prod + shadow».
2. 3 Replayer (запис/відтворення)
Знімок реальних запитів/трейсів (PCAP/NGINX access, gRPC taps) → програвання в «тінь» з контрольованим темпом.
2. 4 «Синтетична тінь»
Генерація навантажувального профілю з прод-логів + фази дозаповнення крайових кейсів - корисна при обмеженнях конфіденційності.
3) Ізоляція стану і сайд-ефектів
Золоте правило: тінь не змінює зовнішній світ.
Рід-онлі доступ до БД/кешу або окрема пісочниця (snapshot/репліка).
Заборона вихідних побочок: платежі, листи, пуши, webhooks → stub/blackhole/record-only.
Ідемпотентність на рівні команд/POST: Shadow не повинен реєструватися як повтор оригіналу.
Маскування PII/секретів, токени тестових провайдерів.
Приклад: маскування в дзеркалі
yaml shadowFilter:
headers:
redact:
- Authorization
- X-Api-Key body:
jsonPaths:
- replace "$ .email" # with token
- "$.card. number"
4) Стратегії семплування та безпечне навантаження
Частка трафіку: 1-10% на старті; підвищувати, якщо v2 вкладається в бюджет.
Критерії відбору: за маршрутом, користувачеві, розміром запиту, типом операції (GET-и безпечніше).
Перф-бюджет: дзеркалювання не повинно збільшувати p95/p99 бойового сервісу. Тінь завжди асинхронна.
Back-pressure: при перегріванні shadow-ланцюжка - дропати тінь, а не бойові запити.
Час: мінімум 24-72 години, щоб покрити добові і пікові патерни.
5) Порівняння результатів: методи та рівні
5. 1 Рівні порівняння
1. Байтовий дифф: тіло відповіді/події один-в-один. Просто, але крихко (таймстемпи, порядок ключів).
2. Семантичний дифф: нормалізуємо і сортуємо поля, ігноруємо епемериди (traceId, timestamps, counters).
3. Бізнес-інваріанти: чи ті ж суми, статуси, кількості, межі.
4. Статистичний аналіз: розподілу метрик збігаються? (p50/p95, KS-тест, χ ² на категоріальні).
5. 2 Політика порівняння
Маски/ignore-списки полів (напр.,'updatedAt','etag').
Точність: абсолютна/відносна похибка для чисел (наприклад, ± 1e-6).
Допуски (tolerance bands): "різниця в ціні ≤ 0. 01», «помилок не більше + 0. 1% відносно prod".
Псевдокод компаратора
pseudo compare(prod, shadow, policy):
a = normalize(prod, policy)
b = normalize(shadow, policy)
diffs = deepDiff(a, b, ignore=policy. ignore, floatTol=policy. floatTol)
invariants_ok = checkInvariants(a, b, policy. invariants)
return Result(diffs, invariants_ok)
5. 3 Зіставлення zapros↔otvet
Обов'язковий Correlation-ID (прокидати в тінь).
Лінковка спанів: shadow-траса отримує link на бойову.
6) Спостережуваність і артефакти порівняння
Метрики:- `shadow_requests_total{route,...}`
- `shadow_discrepancies_total{type=byte|semantic|invariant}`
- `shadow_error_ratio` и `shadow_slo_breach_total`
- Перф: `shadow_latencies_ms{p50,p95,p99}`
- Логи дифів: компактні JSON-дельти за ключами.
- Звітність: щоденний звіт з топ-N розбіжностей, теплові карти за маршрутами/тенантам.
- UI «diff explorer»: фільтри за типом, маршрутом, полем, export в CSV.
7) Особливі випадки і тонкощі
7. 1 Послідовність і консистентність
Shadow-запити можуть приходити пізніше/раніше; нормалізуйте за версіями/годинниками (Lamport/vector) або допусками вікна.
Read-after-write: тінь з read-replica без синхронної реплікації дасть різні відповіді - порівнюйте через лаг-вікна.
7. 2 Кеш/рекомендації
Не змішуйте кеші prod і shadow.
Для ML/рекомендаторів порівнюйте онлайн-метрики та оффлайн-метрики окремо; слідкуйте за drift вхідних ознак.
7. 3 Зовнішні провайдери
Обертайте клієнти record-only/stub-режимом.
Для розрахункових сервісів (податки, курси) - фіксуйте знімок довідників для обох сторін.
8) Зіставлення з канарними/blue-green
Shadow: нульовий ризик для користувачів, але немає реальних сайд-ефектів; чудово для логіки і перфу.
Canary: малий відсоток реальних відповідей від нової версії; вимагає готової стратегії відкату і SLA.
Blue-green: миттєве перемикання після валідації; Shadow часто використовується перед ним.
9) План впровадження (GitOps-стиль)
1. Цілі та метрики: які інваріанти і допуски перевіряємо, який SLO на розбіжності.
2. Трасування: Correlation-ID, розподілені трейс-лінки.
3. Проксі-налаштування: mirror-політика, семплювання, redaction.
4. Ізоляція: пісочниця БД/кеш, заглушки побочок, тестові ключі.
5. Компаратор: нормалізація, ignore-мапи, інваріанти, звіти.
6. Навантажувальний план: старт з 1-5%, зростання до 20-50% при зелених метриках.
7. Спостережуваність: дашборди «розбіжності/перф/обсяг».
8. Критерії виходу: «0 критичних розбіжностей 48 год», «помилки не гірше prod», «перф в межах ± 5%».
9. Перехід до canary: включити реальні відповіді з безпечною часткою і автоматичними гард-правилами.
10) Приклади конфігурацій
10. 1 Istio (Traffic Mirroring)
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService spec:
hosts: ["svc. example"]
http:
- route: [{ destination: { host: svc, subset: v1 } }]
mirror:
host: svc subset: v2 mirrorPercentage:
value: 0. 1 # 10%
10. 2 Kafka Tee (ескіз)
text source-topic -> prod-consumer-group
-> shadow-consumer-group (isolated sink/db)
10. 3 Правила порівняння (yaml-політика)
yaml ignoreFields:
- $.traceId
- $.meta. generatedAt floatTolerance:
default: 1e-6 fields:
$.price: 0. 01 invariants:
- name: "nonNegativeTotal"
expr: "$.total >= 0"
- name: "statusMapping"
expr: "map($.status in ['ok','fail'], true)"
11) Анти-патерни
Shadow пише назовні: реальні платежі/повідомлення з тіні.
Загальний кеш/загальні черги: перехресний вплив і забруднення.
Відсутність нормалізації: байтові диффи «червонять» через години/порядок ключів.
Занадто високий відсоток з ходу: деградація перфу prod.
Довга «вічна тінь»: друга система живе окремо і розходиться з реальністю.
12) Чек-лист запуску Shadow-режиму
- У проксі налаштований mirror з часткою і redaction.
- Тінь ізольована: БД/кеші/зовнішні інтеграції - тільки readonly/stub.
- Скрізь прокинуть Correlation-ID; трасування лінкуються.
- Компаратор вміє ignore/normalize і перевірку інваріантів.
- Дашборди і алерти на розбіжності і навантаження.
- Семплювання за маршрутами/тенантами; ліміти і back-pressure.
- Визначено допуски та критерії «зеленого світла».
- План переходу до canary/blue-green і відкату.
13) FAQ
Q: Чим Shadow відрізняється від A/B?
A: В A/B обидві версії повертають відповіді користувачам (спліт-експеримент), в Shadow нова версія не впливає на користувача - її відповіді тільки аналізуються.
Q: Чи можна шадовити POST/PUT?
A: Так, якщо гарантована ізоляція побочок (stub) і ідемпотентність. Часто починають з GET, потім розширюють.
Q: Як порівнювати відповіді, якщо порядок елементів нефіксований?
A: Сортуйте за стійким ключем перед порівнянням або порівнюйте як множини/за ключами.
Q: Що робити із затримками реплік БД?
A: Вводьте «вікна порівняння» і снапшоти довідників; агрегуйте результати за версіями, а не за «стіночасом».
14) Підсумки
Shadow-трафік - це «безболісна репетиція продакшену»: реальне навантаження, нульовий ризик для користувачів, детальна аналітика розбіжностей. Успіх визначається ізоляцією, правильним семплюванням, якісним компаратором і спостережуваністю. Дотримуючись запропонованого плану, ви отримаєте відтворювану практику, яка впевнено мостить шлях до canary/blue-green релізів і прискорює еволюцію архітектури.