Навантажувальне та стрес-тестування
1) Терміни та цілі
Load test - перевірка в робочому діапазоні (target RPS/конкурентність) проти SLO (наприклад, p95 <200 мс, error rate <0. 5%).
Stress test - вихід за межі (до/понад насичення CPU/БД/мережі), спостереження деградації і механіки відновлення.
Spike test - різкі сплески навантаження (× N протягом хвилин).
Soak/Endurance - тривалий прогін (годинник/доба) для пошуку витоків, дрейфу GC, фрагментації, зростів черг.
Capacity test - обчислення плато пропускної здатності (saturation point) і запасів.
Цілі: підтвердити SLO, зафіксувати плато, зрозуміти вузькі місця, відкалібрувати авто-масштабування і ліміти.
2) Модель трафіку: відкрита vs закрита
Закрита модель (concurrency-driven): фіксоване число віртуальних користувачів (VUs), кожен після відповіді робить think time.
Відкрита модель (arrival-rate): фіксована інтенсивність надходження запитів (RPS), незалежно від відповідей.
Little’s Law: `L = λ W`
«L» - середнє число одночасно обслуговуваних запитів,
«λ» - інтенсивність (RPS),
«W» - середній час відповіді.
Звідси оцінка потрібної конкурентності генератора: `concurrency ≈ target_RPS p95_latency`.
3) Метрики: що вимірюємо
SLI затримок: p50/p90/p95/p99 і хвіст p99. 9; окремі для «гарячих» і «холодних» шляхів.
Помилки: '5xx','4xx'( валідні/невалідні), timeouts, aborted.
Пропускна здатність: стійкий RPS, throughput потоків/байт.
Ресурси: CPU, RAM/heap, GC-паузи, дискова IOPS/lat, мережевий bandwidth, кількість з'єднань/FD.
Черги і бекпрешер: глибина, час очікування, кількість shed/limited запитів.
Ефективність кешу: hit/miss, шторми прогріву.
БД/кеші/черги: p95 запитів, блокування, конфлікти, pool utilization.
4) Стенди і дані
Конфігураційна еквівалентність: версії софта, ліміти (uLimit, conntrack), конфігівка JVM/GC, pool'и.
Топологія: LBs, CDN, WAF, TLS, ті ж мережеві «хопи».
Дані: реалістичні розподіли (розміри об'єктів, «гарячі «/» холодні »ключі, регіональність).
Холодний/теплий/гарячий старт: окремі прогони; обов'язково тестувати «холодні» кеші.
Ізоляція фону: відключити нерелевантні джоби/крономи або врахувати їх ефект.
5) Сценарії (профілі навантаження)
1. Baseline: ступінчастий розгін до цільового RPS, утримання 10-30 хв.
2. Ramp & Hold: плавне зростання до X% вище цілі, утримання → аналіз хвостів.
3. Spike: миттєвий × 2- × 5 сплеск на 1-5 хв, потім повернення.
4. Stress to Failure: сходами вщерть; фіксуємо першу точку невиконання SLO і точку «ломки».
5. Soak: 6-24 год з варіативністю трафіку (день/ніч), стежимо за ликами/дрейфом.
6. Mixed: суміш ендпоінтів за реальним розподілом (Zipf/pareto), різні ваги.
6) Покроковий процес
Визначити SLO і цільові профілі трафіку.
Вибрати модель навантаження (відкрита/закрита), задати arrival-rate або VUs.
Підготувати дані і «гарячі «/» холодні »режими.
Налаштувати телеметрію (трейси/метрики/логи), кореляцію з тест-раном.
Розігрів і прогін, збір артефактів (профілі CPU/heap, flame graphs, explain/slow-logs БД).
Аналіз вузьких місць, формування action items.
Репрогон після фіксів, оновлення базлайну і capacity playbook.
7) Вузькі місця і типові фікси
CPU-bound сервіс: профілювання → усунення гарячих функцій, алокацій, розгалужень; векторизація, кеш-friendly структури.
Мережа/TLS: keep-alive, HTTP/2/3, connection pooling, правильні таймаути, зменшення чатовості.
БД: індекси, батчинги, підготовлені запити, пул конектів, R/W-поділ, кешування результатів, дедуплікація запитів.
Кеші: розмір, TTL, request coalescing, захист від штормів, warming, регіональні кулі.
Черги/брокери: ліміти прийомом/паралелізм, розмір батчів, idempotent consumers, DLQ-стелі.
Гарбатедж/паузи: тюнінг GC, оренда буферів, object pooling в розумних межах.
I/O/диск: асинхронний ввід/вивід, компресія, стиснення відповідей з розумним рівнем.
8) Ліміти та захист
Budget таймаутів: зверху вниз, щоб уникнути каскадів.
Rate limit/токен-бакети: передбачувана деградація замість «довгої смерті».
Circuit breaker і шейдинг низького пріоритету при насиченні.
Backpressure: сигнали і обмеження паралелізму вглиб ланцюжка.
Bulkheads: ізоляція пулів під критичні ендпоінти.
Idempotency: ключі для безпечних повторів під ретраями.
9) Інструменти і коли їх вибирати
k6 - лаконічний JS, відмінна підтримка arrival-rate, інтеграції та графи.
Gatling - Scala DSL, високопродуктивний генератор.
JMeter - гнучкий, багатий екосистемою; зручний для протоколів/плагінів.
Locust - Python-сценарії, зручно для складної логіки призначених для користувача флоу.
Vegeta/hey/wrk - мікробенчі і точкові прогони на HTTP.
tc/netem, toxiproxy - ін'єкція мережевих деградацій.
Flamegraph/profiler - пошук «гарячих місць» CPU/heap.
10) Приклади (скетчі)
k6 (відкрита модель, mix ендпоінтів)
javascript import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
scenarios: {
open_model: {
executor: 'constant-arrival-rate',
rate: 800, timeUnit: '1s', duration: '20m',
preAllocatedVUs: 500, maxVUs: 2000
}
},
thresholds: {
'http_req_duration{kind:hot}': ['p(95)<200'],
'http_req_failed': ['rate<0. 005']
}
};
export default function () {
const r = Math. random();
let res;
if (r < 0. 6) {
res = http. get('https://svc/api/hot', { tags: { kind: 'hot' }});
} else if (r < 0. 9) {
res = http. get('https://svc/api/warm', { tags: { kind: 'warm' }});
} else {
res = http. post('https://svc/api/heavy', JSON. stringify({ n: 1000 }), { headers: { 'Content-Type': 'application/json' }});
}
check(res, { 'status is 2xx': (r) => r. status >= 200 && r. status < 300 });
sleep(0. 2);
}
Gatling (сходи і спайк)
scala setUp(
scn. inject(
rampUsersPerSec(50) to 500 during (10 minutes),
constantUsersPerSec(500) during (20 minutes),
spikeUsers(2000). during(30. seconds)
)
). protocols(http. baseUrl("https://svc"))
Навантажувальний план (YAML-скелет)
yaml profile: "mix-traffic"
targets:
- endpoint: GET /api/hot weight: 0. 6
- endpoint: GET /api/warm weight: 0. 3
- endpoint: POST /api/heavy weight: 0. 1 schedule:
- step: { rps: 300, hold: 10m }
- step: { rps: 600, hold: 10m }
- step: { rps: 900, hold: 10m }
guardrails:
slo:
p95_ms: 200 error_rate: 0. 5%
abort_if:
- metric: error_rate op: ">"
value: 2%
window: 2m
11) Автоматизація та життєвий цикл
Perf-smoke в кожному PR (короткий прогін ключових ендпоінтів).
Нічні «capacity» прогони на стейджі зі звітами та артефактами профілів.
Гейти в CI/CD: фейл білда при регресі p95/p99> X% від базлайну або зростанні error rate.
Версіонування базлайнів і зберігання профілів/флеймграфів як артефактів.
Теги релевантності: який сервіс/ендпоінт покритий, який профіль трафіку використаний.
12) Анти-патерни
Генератор і тестований сервіс на одній машині → спотворені результати.
Тільки закрита модель (VUs) для API-беків → заниження хвостів і невірна оцінка.
Прогони по порожній БД/кешу без холодного старту.
Відсутність реалістичних розподілів (всі запити однакові).
Немає телеметрії (тільки RPS/latency з боку генератора).
Порівняння без стабільних базлайнів і контролю середовища.
«Оптимізація» через збільшений таймаут замість виправлення причини.
13) Чек-лист архітектора
1. Визначено SLO та типове/пікове навантаження?
2. Обрано коректну модель (open/closed) та розписано профіль трафіку?
3. Стенд еквівалентний по конфігам і топології, є холодний/гарячий режим?
4. Телеметрія і профілі включені, мітки тест-рана проставляються?
5. Прогони: baseline/ramp/spike/stress/soak - покриті?
6. Фіксуються точки насичення і планується запас (safety margin)?
7. Налаштовані ліміти, брейкери, бекпрешер, idempotency, поліси шейдингу?
8. Є CI-гейти на регрес p95/p99 і error rate, базлайни версіоновані?
9. Після фіксів - репрогон і оновлення playbook за потужністю?
10. Документовано план авто-масштабування та аварійних режимів?
Висновок
Навантажувальне і стрес-тестування - це не разові «гонки», а безперервна інженерна практика. Реалістична модель трафіку, коректні стенди, телеметрія і автоматизація в CI/CD перетворюють продуктивність з «таємної магії» в керовану метриками здатність: ви знаєте, де ваша стеля, наскільки безпечний запас і які зміни реально покращують досвід користувачів.