Навантажувальне тестування з k6: від першого скрипта до порогів
Як написати навантажувальний тест на JavaScript, змоделювати реалістичне навантаження, задати пороги якості і не зробити типових помилок в інтерпретації результатів.
Функціональні тести відповідають на питання «чи працює?». Навантажувальні — «чи працюватиме, коли прийдуть користувачі?». k6 — інструмент від Grafana Labs, у якому сценарії пишуться на JavaScript, а запускаються одним бінарним файлом.
Перший скрипт
// smoke.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 5, // віртуальних користувачів
duration: '1m',
};
export default function () {
const res = http.get('https://staging.example.com/api/products?limit=20');
check(res, {
'статус 200': (r) => r.status === 200,
'є товари': (r) => r.json('items').length > 0,
});
sleep(1); // пауза «користувача» між діями
}k6 run smoke.jsКожен віртуальний користувач (VU) у циклі виконує функцію default. Наприкінці k6 виводить зведення: кількість запитів, частку помилок і розподіл часу відповіді.
Типи тестів
| Тип | Мета | Профіль навантаження |
|---|---|---|
| Smoke | Скрипт працює, система жива | 1–5 VU, 1 хв |
| Load | Поведінка при очікуваному навантаженні | Плавний ріст до цільового, 15–30 хв |
| Stress | Де межа і як система деградує | Ріст вище очікуваного |
| Spike | Різкий сплеск (розсилка, реклама) | Стрибок у 5–10 разів за секунди |
| Soak | Витоки пам'яті, переповнення пулів | Помірне навантаження 2–8 год |
Реалістичне навантаження: сценарії та arrival rate
Кількість VU — погана метрика: якщо сервер сповільнився, VU роблять менше запитів, і навантаження саме собою падає. Для API краще задавати швидкість надходження запитів:
export const options = {
scenarios: {
browse: {
executor: 'ramping-arrival-rate',
startRate: 10,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 300,
stages: [
{ target: 100, duration: '5m' }, // ріст до 100 запитів/с
{ target: 100, duration: '15m' }, // тримаємо
{ target: 0, duration: '2m' },
],
},
},
};Пороги: тест має падати
Без порогів навантажувальний тест — просто генератор графіків. Thresholds перетворюють його на перевірку, яка може зламати пайплайн:
export const options = {
thresholds: {
http_req_failed: ['rate<0.01'], // помилок менше 1%
http_req_duration: ['p(95)<400', 'p(99)<1000'], // 95% запитів швидше за 400 мс
'http_req_duration{name:checkout}': ['p(95)<800'],
},
};ВажливоДивіться на перцентилі, а не на середнє. Середнє 200 мс може приховувати те, що кожен двадцятий користувач чекає 5 секунд. p95 і p99 показують досвід «невдах» — а їх при великій кількості запитів дуже багато.
Сценарій користувача з даними
import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { SharedArray } from 'k6/data';
const users = new SharedArray('users', () => JSON.parse(open('./users.json')));
export default function () {
const user = users[__VU % users.length];
group('login', () => {
const res = http.post(`${__ENV.BASE_URL}/api/login`, JSON.stringify(user), {
headers: { 'Content-Type': 'application/json' },
tags: { name: 'login' },
});
check(res, { 'вхід успішний': (r) => r.status === 200 });
});
group('checkout', () => {
const res = http.post(`${__ENV.BASE_URL}/api/checkout`, '{"cartId":"demo"}', {
headers: { 'Content-Type': 'application/json' },
tags: { name: 'checkout' },
});
check(res, { 'замовлення створено': (r) => r.status === 201 });
});
sleep(Math.random() * 3 + 1);
}ПорадаТег
nameгрупує запити з різними URL (/orders/1,/orders/2…) в одну метрику. Без нього звіт розсиплеться на тисячі рядків.
Типові помилки
- Генератор навантаження — вузьке місце. Слідкуйте за CPU машини з k6; якщо вона завантажена на 100%, результати брешуть.
- Тест проти продакшену без попередження. Узгодьте з командою, вимкніть алерти або тестуйте на окремому середовищі.
- Кеш «прикрашає» результати. 10 000 однакових запитів до одного товару — це тест кешу, а не бази.
- Немає базової лінії. Зберігайте результати попередніх прогонів і порівнюйте тренд, а не одне число.
- Дивитись лише на k6. Паралельно дивіться метрики сервера: CPU, пам'ять, з'єднання з БД, довжину черг. Саме там видно, чому p95 виріс.
Чому для тестування API краще задавати arrival rate, а не кількість VU?
При фіксованій кількості VU кожен користувач чекає відповіді перед наступним запитом. Якщо сервер сповільнюється, запитів стає менше — і тест «пом'якшує» навантаження саме тоді, коли треба його тримати. Arrival rate підтримує задану кількість запитів за секунду незалежно від швидкості відповідей.
Збережіть статтю собі
Увійдіть, щоб імпортувати її у власні нотатки, відмічати вивчене, ставити лайки й питати спільноту. Реєстрація безкоштовна: вхід через Google займає кілька секунд.
Увійти через Google Інші способи входу