Навантажувальне тестування та стрес
Навантажувальне тестування та стрес
1) Навіщо це потрібно
Цілі:- Підтвердити ємність (скільки RPS/конкурентних сесій витримає система при заданому SLO).
- Знайти пляшкові горлечка (CPU/IO/БД/мережі/блокування/пули).
- Налаштувати перформанс-бюджети і «гейти» в CI/CD.
- Знизити ризик релізів (регресії p95/p99, зростання помилок при піку).
- Спланувати ємність/вартість (скейл-аут і резерви).
2) Типи перф-тестів
Load (робоче навантаження): реалістичний трафік близький до піків; валідація SLO.
Stress (стрес): зростання до/вище межі → поведінку при деградації, де ламається.
Spike (імпульс): швидкий стрибок навантаження → еластичність/автоскейл.
Soak/Endurance (тривалий): годинник/добу → витоку, фрагментація, дрейф latency.
Capacity/Scalability: як змінюється throughput/latency при scale-out; закон Амдала/Густафсона.
Smoke perf: короткий «димовий» прогін на кожному релізі (перформанс-саніті).
3) Моделі генерації трафіку
Закрита модель (fixed VUs/concurrency): «N» користувачів, кожен робить запити → чергу в клієнті. Ризик приховати перевантаження.
Відкрита модель (arrival rate): потік заявок з інтенсивністю λ (req/s), як в реальному житті. Коректніше для публічних API.
Закон Літтла: `L = λ × W`.
Для пулу/сервісу: мінімальний паралелізм ≈'λ × W'( додайте 20-50% запасу).
Де'λ'- throughput,'W'- середній час обслуговування.
4) Профілі навантаження і сценарії
User journey mix: частки сценаріїв (login, browse, deposit, checkout...).
Think-time: паузи користувача (розподілу: експоненціальне/логнормальне).
Data profile: розмір відповідей, payload, варіативність параметрів.
Кореляція: зв'язуйте кроки (куки/токени/ID) як в реальному флоу.
Холод/теплий/гарячий кеш: окремі прогони.
Read vs Write: баланс читань/записів, ідемпотентність для ретраїв.
Мульти-регіон: RTT, розподіл по POP/ASN.
5) Середовище тестування
Ізоляція: стенд близький до проду з топології/налаштувань (але не «б'ємо» прод).
Дані: маскування PII, обсяги, індекси як у проді.
Генератори навантаження: не впираються в CPU/мережу; розподілені раннери, синхронізація часу.
Спостережуваність: метрики/трейси/логи, синтетика на периметрі, експорт профілів CPU/heap.
6) Метрики та SLI
Throughput: RPS/транзакції в сек.
Latency: p50/p95/p99, TTFB, server time vs network.
Errors: частка 5хх/4хх/доменних помилок.
Saturation: CPU, load avg, GC, дискові IOps/латентність, network, pool wait.
Бізнес-SLI: успіх депозиту ≤ 5s, підтвердження замовлення ≤ 2s.
Порогові значення беріть із SLO (наприклад, "99. 95% ≤ 300 ms"), моніторьте burn-rate під час прогону.
7) Пошук вузьких місць (методика)
1. Стабільно прогрійте систему на 60-80% цільового навантаження.
2. Збільшуйте ступенями (ramp) → фіксуйте де росте p95/p99 і error-rate.
- чергами в пулах (DB/HTTP),
- зростанням WAIT/локів (БД),
- GC-паузи/heap,
- мережеві retransmits/packet loss,
- дискова латентність/кеш-промахи.
- 4. Локалізуйте: бінарний пошук по шляху запиту, профілювальники (CPU/alloc/lock-profile).
- 5. Фіксуйте «пляшку» → тюнінг → повтор прогону.
8) Поведінка під стресом
Graceful degradation: ліміти, circuit-breakers, черги з backpressure, режим «прийнято в обробку».
Ретраї: максимум 1, тільки ідемпотентні; джиттер; бюджет ретраїв ≤ 10% від RPS.
Fail-open/Fail-closed: для не-критичних залежностей допускайте fail-open (кеш/заглушки).
Cascading failure: ізоляція пулів/квоти (bulkhead), швидкі таймаути, «плавне» відключення функцій (feature flags).
9) Інструменти (вибір під задачу)
k6 (JavaScript, відкрита/open-model, швидкий, зручний в CI).
JMeter (багатий екосистемою, GUI/CLI, плагіни, але важче).
Gatling (Scala DSL, висока продуктивність).
Locust (Python, гнучкість сценаріїв).
Vegeta/hey/wrk (мікро-бенчі і швидка перевірка).
Правило: один «основний» інструмент + легкий CLI для smoke-перф в PR.
10) Приклади (сніпети)
10. 1 k6 (відкрита модель з arrival rate)
js import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
scenarios: {
open_model: {
executor: 'ramping-arrival-rate',
startRate: 200, timeUnit: '1s',
preAllocatedVUs: 200, maxVUs: 2000,
stages: [
{ target: 500, duration: '5m' }, // до 500 rps
{target: 800, duration: '5m'} ,//stress
{ target: 0, duration: '1m' }
]
}
},
thresholds: {
http_req_duration: ['p(95)<300', 'p(99)<800'],
http_req_failed: ['rate<0. 005'],
},
};
export default function () {
const res = http. get(`${__ENV. BASE_URL}/api/catalog? limit=20`);
sleep(Math. random() 2); // think-time
}
10. 2 JMeter (ідея профілю)
Thread Group + Stepping Thread или Concurrency Thread (open-like).
HTTP Request Defaults, Cookie Manager, CSV Data Set.
Backend Listener → InfluxDB/Grafana; Assertions за часом/кодом.
10. 3 Locust (Python)
python from locust import HttpUser, task, between class WebUser(HttpUser):
wait_time = between(0. 2, 2. 0)
@task(5)
def browse(self): self. client. get("/api/catalog? limit=20")
@task(1)
def buy(self): self. client. post("/api/checkout", json={"sku":"A1","qty":1})
11) Дані, кореляція, підготовка
Seed-дані: каталоги, користувачі, баланси, токени - як у проді.
Маскування/анонімізація PII; генерація синтетики поверх реальних розподілів.
Кореляція: витягуйте ID/токени з відповідей (RegExp/JSONPath) і використовуйте в наступних кроках.
12) Спостережуваність під час прогонів
RED-дашборди (Rate, Errors, Duration) за маршрутами.
Exemplars: перехід з метрик до трас (trace_id).
Логи помилок: семплінг + агрегація, дублікати/ідемпотентність.
Системні: CPU/GC/heap, диски/мережа, pool wait.
БД: топ-запити, блокування, індекс-скани, bloat.
13) Автоматизація та перформанс-гейти
CI: короткі прогони на merge (наприклад, k6 2-3 хвилини) з порогами.
Nightly/Weekly: довгі soak/stress в окремому середовищі; звіти і тренди.
Канарські релізи: аналіз SLO (error-rate, p95) як «гейт» промоушену.
Регресії: baseline vs поточний білд; алерти при погіршенні> X%.
14) Планування ємності і вартість
Криві throughput→latency: визначте knee point (коліно) - після нього p99 зростає різко.
Скейл-аут: вимірюйте ефективність масштабування (дельта RPS/дельта вузлів).
Вартість: «RPS на $/год», резерв на пікові події + DR-резерв.
15) Анти-патерни
Бити в прод без контролю або тестувати в «порожньому» середовищі, не схожому на прод.
Закрита модель з фіксованими VU, що приховує перевантаження.
Відсутність think-time/даних → нереалістичні хіти кеша або навпаки - шторму до вихідних.
Один сценарій «/ping »замість призначених для користувача флоу.
Відсутність спостережуваності: «бачимо тільки RPS і середню затримку».
Безконтрольні ретраї → само-DDoS.
Змішування тесту і оптимізацій без фіксації гіпотез/змін.
16) Чек-лист (0-30 днів)
0-7 днів
Визначте SLI/SLO і цільові профілі трафіку (mix, think-time, дані).
Виберіть інструмент (k6/JMeter/Locust), підніміть дашборди RED.
Підготуйте стенд і seed-дані, відключіть сторонні ліміти/каптчі.
8-20 днів
Побудуйте сценарії: open-model (arrival rate), холод/теплий/гарячий кеш.
Запустіть load → stress → spike; зафіксуйте knee point і вузькі місця.
Впроваджуйте перформанс-гейти в CI (мікро-прогін).
21-30 днів
Soak-тест 4-24 год: витоку/дрейф GC, стабілізація.
Документуйте межі, план ємності, ілюстрації «RPS→p95/oshibki».
Підготуйте runbook «як збільшувати ліміти/скейл» і «як деградувати».
17) Метрики зрілості
Є реалістичні профілі (mix, think-time, дані), що покривають ≥ 80% трафіку.
RED-дашборди + трасування підключені для всіх тестів.
Перформанс-гейти блокують релізи при регресії р95/помилок.
Ємність і knee point документовані за ключовими сервісами.
Щомісячні soak/stress-прогони і звіти по динаміці.
Стійкість до «spike» підтверджена автоскейлом і відсутністю cascade-fail.
18) Висновок
Навантажувальне тестування - це регулярна інженерна практика, а не разовий «завмер». Моделюйте реальних користувачів (open-model), міряйте те, що відображає досвід клієнта (SLI/SLO), тримайте спостережуваність і «гейти» в CI/CD, проводьте stress/spike/soak-прогони і фіксуйте knee point. Тоді пікові події і «чорні лебеді» перетворюються в керовані сценарії, а продуктивність - в передбачуваний і вимірний параметр вашої платформи.