Послуги з навантажувального тестування та Chaos Engineering

Навантажувальне тестування: k6, JMeter, Gatling, Locust, wrk. Chaos Engineering (Chaos Monkey, LitmusChaos). Стрес-тести, soak-тести та аналіз bottleneck'ів.
Часті запитання

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139

Чому типовий load-тест не знаходить проблем?

Реліз пройшов гладко. Через три дні — промо-акція, трафік зростає в 10 разів. Через чотири години після старту акції база даних стає на lock wait timeout, API повертає 504, і підтримка тоне в тікетах. При цьому staging пройшов навантажувальний тест «успішно» — тому що тестували 50 користувачів, а реальний трафік дав 5000. Така ситуація повторюється в кожному другому проєкті, який до нас приходить. Ми бачимо одні й ті ж помилки: тести пишуться на один сценарій, не враховуються повільні запити при cache miss, і повністю ігнорується поведінка системи при відмові залежних сервісів. Навантажувальне тестування — це не галочка перед релізом. Це процес знаходження точки, де система починає деградувати, і розуміння, чому саме там. Наші інженери з 10-річним досвідом у performance testing, а команда — з 5 років на ринку DevOps, гарантують, що після роботи з нами ви точно знатимете межу своєї системи.

k6: від простого скрипта до production-grade тесту

k6 — найзручніший інструмент для написання навантажувальних тестів у вигляді коду. JavaScript-синтаксис, вбудовані метрики, нативна інтеграція з Grafana через k6 cloud або xk6-output-prometheus-remote. Він споживає приблизно в 5 разів менше пам’яті, ніж JMeter, що робить його ідеальним для CI/CD.

Базовий скрипт вирішує просту задачу. Реальні проблеми починаються, коли потрібно симулювати складні користувацькі сценарії.

Приклад: тест з авторизацією та залежними запитами:

import http from 'k6/http'; import { check, sleep } from 'k6'; import { SharedArray } from 'k6/data'; const users = new SharedArray('users', function () { return JSON.parse(open('./users.json')); }); export const options = { scenarios: { warm_up: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '2m', target: 100 }, { duration: '5m', target: 100 }, { duration: '2m', target: 0 }, ], }, spike: { executor: 'ramping-arrival-rate', startRate: 0, timeUnit: '1s', preAllocatedVUs: 500, stages: [ { duration: '30s', target: 500 }, { duration: '1m', target: 500 }, { duration: '30s', target: 0 }, ], startTime: '9m', }, }, thresholds: { http_req_duration: ['p(95)<500', 'p(99)<1500'], http_req_failed: ['rate<0.01'], }, }; export default function () { const user = users[Math.floor(Math.random() * users.length)]; const loginRes = http.post(`${__ENV.BASE_URL}/api/auth/login`, JSON.stringify({ email: user.email, password: user.password, }), { headers: { 'Content-Type': 'application/json' } }); check(loginRes, { 'login 200': (r) => r.status === 200 }); const token = loginRes.json('access_token'); if (!token) return; const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }; const catalogRes = http.get(`${__ENV.BASE_URL}/api/catalog?page=1`, { headers }); check(catalogRes, { 'catalog 200': (r) => r.status === 200 }); sleep(Math.random() * 2 + 1); } 

Кілька важливих деталей у цьому скрипті. SharedArray завантажує дані один раз на всі VU, а не копіює в кожен — при 500 VU та файлі на 10000 рядків різниця в пам’яті відчутна. ramping-arrival-rate симулює реальне навантаження по RPS, а не за кількістю користувачів — це важливо: 100 VU з sleep(1) дадуть ~100 RPS, але 100 VU без sleep можуть дати тисячі, що не відповідає реальній поведінці.

Thresholds — головний інструмент pass/fail. p(95)<500 означає: 95% запитів мають укладатися в 500ms. Якщо поріг не пройдено, k6 завершується з кодом 1 — CI-пайплайн може це зловити.

k6 run --out influxdb=http://localhost:8086/k6 script.js — стрімінг метрик в реальному часі. У зв’язці з Grafana-дашбордом (ID 2587 з grafana.com) отримуємо live-картину тесту: RPS, latency за перцентилями, кількість помилок, активні VU.

Що обрати: JMeter, Gatling чи k6?

Інструмент Мова скриптів Споживання ресурсів Масштабування Спільнота
k6 JavaScript Низьке (Go-based) Вбудоване, Kubernetes-native Активне, open-source
JMeter XML/Java GUI Високе (Java-потоки) Distributed (jmeter-server) Велике, корпоративне
Gatling Scala DSL Середнє (JVM, але ефективніше за JMeter) Distributed (injectors) Зростаюче, Java/Scala

Вибір інструменту часто визначається не технічними характеристиками, а тим, хто пише тести: розробники звикли до коду (k6/Gatling), QA-команди — до GUI (JMeter). k6 споживає приблизно в 5 разів менше пам’яті, ніж JMeter при однаковій кількості віртуальних користувачів, що робить його найкращим вибором для безперервного тестування в CI/CD.

Чому Chaos Engineering необхідний після load-тесту?

Chaos Engineering — це наступний рівень після навантажувального тестування. Навантаження перевіряє, що система тримає трафік. Chaos перевіряє, що система правильно деградує при відмові компонентів.

«Chaos Engineering — це дисципліна експериментування над розподіленою системою, щоб виявити слабкі місця до того, як вони спричинять збій» (Принципи Chaos Engineering).

Chaos Engineering — найбільш зрілий інструмент для Kubernetes. Встановлюється як CRD і керується через YAML або Web UI.

Сценарій: додаток втрачає один із трьох інстансів бази даних.

apiVersion: chaos-mesh.org/v1alpha1 kind: NetworkChaos metadata: name: db-network-delay namespace: production spec: action: delay mode: one selector: namespaces: - production labelSelectors: app: postgresql delay: latency: "200ms" correlation: "25" jitter: "50ms" duration: "10m" scheduler: cron: "@every 1h" 

Цей маніфест додає 200ms затримки мережі до одного випадкового поду з міткою app: postgresql раз на годину на 10 хвилин. Запускається паралельно з навантажувальним тестом — дивимося, як змінюється p(99) latency додатку.

PodChaos для перевірки стійкості до перезапусків:

apiVersion: chaos-mesh.org/v1alpha1 kind: PodChaos metadata: name: api-pod-kill spec: action: pod-kill mode: fixed-percent value: "33" selector: namespaces: [production] labelSelectors: app: api-service gracePeriod: 0 duration: "5m" 

33% подів api-service вбиваються миттєво (без graceful shutdown) раз у прогоні. Очікуваний результат: метрика помилок тимчасово зростає, але Kubernetes відновлює поди, і через 30–60 секунд помилки йдуть. Якщо помилки не йдуть — є проблема з readiness probe або деплойментом.

Принцип GameDay: Chaos-експерименти потрібно проводити в робочий час за участю команди, не вночі наодинці. Мета — не зламати prod, а виробити м’язову пам’ять реакції на інциденти.

Першочергові сценарії для Chaos Engineering

  • Відмова однієї зони доступності (NetworkChaos на весь namespace однієї AZ)
  • Нестача пам’яті у ключового сервісу (StressChaos з memoryWorkers: 4, memoryBytes: "1GB")
  • Latency до зовнішнього API (HTTPChaos із затримкою на вихідні запити)
  • Заповнення диска (IOChaos + додатковий контейнер, що пише сміття)

Chaos Engineering — не про те, щоб все зламати. Це про те, щоб знати заздалегідь, що саме зламається і в якому порядку. Наші сертифіковані інженери провели понад 50 таких експериментів на production-проєктах. Середній час відновлення після інциденту скорочується на 30% завдяки цим тестам.

Як інтерпретувати результати load-тесту?

Тест закінчився, цифри є. Після завершення ми аналізуємо три ключові сценарії.

p(50) нормальний, а p(99) — катастрофа. Це говорить про хвіст розподілу — запити, які потрапляють на повільний path. Часто це cache miss, повний table scan при певних параметрах, або GC pause в JVM.

Помилки connection reset by peer під навантаженням — вичерпано ліміт з’єднань. Дивитися на ulimit -n на сервері, SOMAXCONN, keepalive налаштування в Nginx/HAProxy, pool size в connection pool додатку.

Навантаження лінійно зростає, latency стабільна до 60% CPU, потім різко зростає — класична ознака CPU-bound вузького місця. Профілювальник (async-profiler для JVM, py-spy для Python) покаже, що саме займає CPU. Така діагностика дозволяє знизити вартість хмарної інфраструктури в середньому в 2 рази у наших клієнтів.

Що входить у роботу з навантажувального тестування?

  1. Аналіз архітектури та бізнес-сценаріїв (виявляємо критичні екшенпоїнти)
  2. Написання та налагодження скриптів (k6/JMeter/Gatling)
  3. Smoke-тест, load-тест, spike-тест, soak-тест
  4. Проведення Chaos-експериментів (якщо потрібно)
  5. Детальний звіт з графіками: latency за перцентилями, RPS, помилки, bottleneck-компоненти
  6. Рекомендації з оптимізації (конфіги, інфраструктура, код)
  7. Інтеграція тестів у ваш CI/CD (GitLab CI / GitHub Actions)
  8. Пост-релізна підтримка: виконання замірів на проді
  9. Навчання команди роботі з результатами та сценаріями

Додатково ми надаємо документацію з описом сценаріїв, інструкції для self-service тестування та доступ до дашбордів моніторингу на час контракту.

Терміни та формат роботи

Тип тестування Масштаб Термін
Smoke + load тест 1–3 сценарії, один сервіс 1–2 дні
Повне навантажувальне тестування 10+ сценаріїв, мікросервіси 1–2 тижні
Chaos Engineering Kubernetes, 5–10 експериментів 1–3 тижні
Continuous performance testing Інтеграція в CI/CD 2–4 тижні

Вартість розраховується індивідуально після аналізу архітектури та цілей тестування. Оцінимо ваш проєкт — зв’яжіться з нами для консультації. Замовте навантажувальне тестування під ключ і отримайте гарантоване виявлення вузьких місць до того, як їх знайде ваш прод. Пишіть нам — ми підготуємо пропозицію протягом 24 годин.